Skip to content
Snippets Groups Projects
modify_partners.py 2.85 KiB
"""A modification workflow that modifies a partner."""

from orchestrator.forms import FormPage
from orchestrator.targets import Target
from orchestrator.types import FormGenerator, State, UUIDstr
from orchestrator.workflow import StepList, begin, done, step, workflow
from pydantic import ConfigDict, EmailStr, field_validator
from pydantic_forms.validators import Choice

from gso.services.partners import (
    ModifiedPartnerSchema,
    edit_partner,
    filter_partners_by_email,
    filter_partners_by_name,
    get_all_partners,
    get_partner_by_name,
)


def initial_input_form_generator() -> FormGenerator:
    """Gather input from the user needed for modifying a partner."""
    partners = {}
    for partner in get_all_partners():
        partners[partner["partner_id"]] = partner["name"]

    partner_choice = Choice("Select a partner", zip(partners.values(), partners.items(), strict=True))  # type: ignore[arg-type]

    class SelectPartnerForm(FormPage):
        model_config = ConfigDict(title="Choose a Partner")

        partners: partner_choice  # type: ignore[valid-type]

    initial_user_input = yield SelectPartnerForm

    partner = get_partner_by_name(name=initial_user_input.partners.name)

    class ModifyPartnerForm(FormPage):
        model_config = ConfigDict(title="Modify a Partner")

        name: str | None = partner["name"]
        email: EmailStr | None = partner["email"]

        @field_validator("name")
        def validate_name(cls, name: str) -> str | None:
            if partner["name"] == name:
                return None
            if filter_partners_by_name(name=name, case_sensitive=False):
                msg = "Partner with this name already exists."
                raise ValueError(msg)
            return name

        @field_validator("email")
        def validate_email(cls, email: str) -> EmailStr | None:
            if partner["email"] == email:
                return None
            if filter_partners_by_email(email=email, case_sensitive=False):
                msg = "Partner with this email already exists."
                raise ValueError(msg)
            return email

    user_input = yield ModifyPartnerForm

    return user_input.model_dump() | {"partner_id": partner["partner_id"]}


@step("Save partner information to database")
def save_partner_to_database(
    partner_id: UUIDstr,
    name: str | None,
    email: EmailStr | None,
) -> State:
    """Save modified partner in database."""
    partner = edit_partner(
        partner_data=ModifiedPartnerSchema(
            partner_id=partner_id,
            name=name,
            email=email,
        )
    )

    return {"modified_partner": partner}


@workflow(
    "Modify partners",
    initial_input_form=initial_input_form_generator,
    target=Target.SYSTEM,
)
def task_modify_partners() -> StepList:
    """Modify a Partner."""
    return begin >> save_partner_to_database >> done