"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from __future__ import annotations
from ascend_sdk import utils
from ascend_sdk.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from ascend_sdk.utils import validate_open_enum
from enum import Enum
import pydantic
from pydantic import model_serializer
from pydantic.functional_validators import PlainValidator
from typing import List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class AddressTypedDict(TypedDict):
    r"""The address of the person or entity taking receipt of the wired funds. This will be populated automatically in the case of a valid first-party wire"""

    city: NotRequired[str]
    r"""Required: Describes the city in which the entity is located."""
    country: NotRequired[str]
    r"""Required: The country code used for geolocation, identity verification, and/or mail delivery purposes."""
    postal_code: NotRequired[str]
    r"""Required: The postal code used for geolocation, identity verification, and/or mail delivery purposes."""
    state: NotRequired[str]
    r"""Required: The state code used for geolocation, identity verification, and/or mail delivery purposes."""
    street_address: NotRequired[List[str]]
    r"""The street name and number relating to a party's legal or mailing address."""


class Address(BaseModel):
    r"""The address of the person or entity taking receipt of the wired funds. This will be populated automatically in the case of a valid first-party wire"""

    city: Optional[str] = None
    r"""Required: Describes the city in which the entity is located."""

    country: Optional[str] = None
    r"""Required: The country code used for geolocation, identity verification, and/or mail delivery purposes."""

    postal_code: Optional[str] = None
    r"""Required: The postal code used for geolocation, identity verification, and/or mail delivery purposes."""

    state: Optional[str] = None
    r"""Required: The state code used for geolocation, identity verification, and/or mail delivery purposes."""

    street_address: Annotated[
        Optional[List[str]], pydantic.Field(alias="streetAddress")
    ] = None
    r"""The street name and number relating to a party's legal or mailing address."""


class WireWithdrawalScheduleBeneficiaryTypedDict(TypedDict):
    r"""The beneficiary of the wire withdrawal"""

    account: NotRequired[str]
    r"""The bank account of the person or entity taking receipt of the wired funds. Limited to 25 characters if intermediaryDetails.account is set"""
    account_title: NotRequired[str]
    r"""The name of the person or entity taking receipt of the wired funds. This field defaults to the name of the account owner and should only be populated when performing a third party wire transfer"""
    address: NotRequired[Nullable[AddressTypedDict]]
    r"""The address of the person or entity taking receipt of the wired funds. This will be populated automatically in the case of a valid first-party wire"""
    third_party: NotRequired[bool]
    r"""Indicates if this beneficiary is a third party beneficiary. A wire transfer is considered third party if the beneficiary is not the exact same person and/or entity that the funds originated from. This includes wire transfers where the originator account is an individual account and the beneficiary account is a joint account"""


class WireWithdrawalScheduleBeneficiary(BaseModel):
    r"""The beneficiary of the wire withdrawal"""

    account: Optional[str] = None
    r"""The bank account of the person or entity taking receipt of the wired funds. Limited to 25 characters if intermediaryDetails.account is set"""

    account_title: Optional[str] = None
    r"""The name of the person or entity taking receipt of the wired funds. This field defaults to the name of the account owner and should only be populated when performing a third party wire transfer"""

    address: OptionalNullable[Address] = UNSET
    r"""The address of the person or entity taking receipt of the wired funds. This will be populated automatically in the case of a valid first-party wire"""

    third_party: Optional[bool] = None
    r"""Indicates if this beneficiary is a third party beneficiary. A wire transfer is considered third party if the beneficiary is not the exact same person and/or entity that the funds originated from. This includes wire transfers where the originator account is an individual account and the beneficiary account is a joint account"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["account", "account_title", "address", "third_party"]
        nullable_fields = ["address"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleAddressTypedDict(TypedDict):
    r"""The address of the intermediary party"""

    city: NotRequired[str]
    r"""Required: Describes the city in which the entity is located."""
    country: NotRequired[str]
    r"""Required: The country code used for geolocation, identity verification, and/or mail delivery purposes."""
    postal_code: NotRequired[str]
    r"""Required: The postal code used for geolocation, identity verification, and/or mail delivery purposes."""
    state: NotRequired[str]
    r"""Required: The state code used for geolocation, identity verification, and/or mail delivery purposes."""
    street_address: NotRequired[List[str]]
    r"""The street name and number relating to a party's legal or mailing address."""


class WireWithdrawalScheduleAddress(BaseModel):
    r"""The address of the intermediary party"""

    city: Optional[str] = None
    r"""Required: Describes the city in which the entity is located."""

    country: Optional[str] = None
    r"""Required: The country code used for geolocation, identity verification, and/or mail delivery purposes."""

    postal_code: Optional[str] = None
    r"""Required: The postal code used for geolocation, identity verification, and/or mail delivery purposes."""

    state: Optional[str] = None
    r"""Required: The state code used for geolocation, identity verification, and/or mail delivery purposes."""

    street_address: Annotated[
        Optional[List[str]], pydantic.Field(alias="streetAddress")
    ] = None
    r"""The street name and number relating to a party's legal or mailing address."""


class IntermediaryTypedDict(TypedDict):
    r"""The intermediary party"""

    account: NotRequired[str]
    r"""The account number of the intermediary party"""
    account_title: NotRequired[str]
    r"""The name of the intermediary party"""
    address: NotRequired[Nullable[WireWithdrawalScheduleAddressTypedDict]]
    r"""The address of the intermediary party"""


class Intermediary(BaseModel):
    r"""The intermediary party"""

    account: Optional[str] = None
    r"""The account number of the intermediary party"""

    account_title: Optional[str] = None
    r"""The name of the intermediary party"""

    address: OptionalNullable[WireWithdrawalScheduleAddress] = UNSET
    r"""The address of the intermediary party"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["account", "account_title", "address"]
        nullable_fields = ["address"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleRecipientBankType(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The type of bank identifier specified"""

    TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED"
    ABA = "ABA"
    BIC = "BIC"


class BankIDTypedDict(TypedDict):
    r"""An identifier that represents ABA routing number for domestic wire or BIC for foreign wire"""

    id: NotRequired[str]
    r"""The bank identifier"""
    type: NotRequired[WireWithdrawalScheduleRecipientBankType]
    r"""The type of bank identifier specified"""


class BankID(BaseModel):
    r"""An identifier that represents ABA routing number for domestic wire or BIC for foreign wire"""

    id: Optional[str] = None
    r"""The bank identifier"""

    type: Annotated[
        Optional[WireWithdrawalScheduleRecipientBankType],
        PlainValidator(validate_open_enum(False)),
    ] = None
    r"""The type of bank identifier specified"""


class WireWithdrawalScheduleRecipientBankAddressTypedDict(TypedDict):
    r"""The address of the recipient bank / financial institution"""

    city: NotRequired[str]
    r"""Required: Describes the city in which the entity is located."""
    country: NotRequired[str]
    r"""Required: The country code used for geolocation, identity verification, and/or mail delivery purposes."""
    postal_code: NotRequired[str]
    r"""Required: The postal code used for geolocation, identity verification, and/or mail delivery purposes."""
    state: NotRequired[str]
    r"""Required: The state code used for geolocation, identity verification, and/or mail delivery purposes."""
    street_address: NotRequired[List[str]]
    r"""The street name and number relating to a party's legal or mailing address."""


class WireWithdrawalScheduleRecipientBankAddress(BaseModel):
    r"""The address of the recipient bank / financial institution"""

    city: Optional[str] = None
    r"""Required: Describes the city in which the entity is located."""

    country: Optional[str] = None
    r"""Required: The country code used for geolocation, identity verification, and/or mail delivery purposes."""

    postal_code: Optional[str] = None
    r"""Required: The postal code used for geolocation, identity verification, and/or mail delivery purposes."""

    state: Optional[str] = None
    r"""Required: The state code used for geolocation, identity verification, and/or mail delivery purposes."""

    street_address: Annotated[
        Optional[List[str]], pydantic.Field(alias="streetAddress")
    ] = None
    r"""The street name and number relating to a party's legal or mailing address."""


class InternationalBankDetailsTypedDict(TypedDict):
    r"""Bank details required in the case of an international wire transfer"""

    additional_info: NotRequired[str]
    r"""Any additional information to be communicated to the recipient bank, such as intermediary banks to be used."""
    address: NotRequired[Nullable[WireWithdrawalScheduleRecipientBankAddressTypedDict]]
    r"""The address of the recipient bank / financial institution"""
    bank_name: NotRequired[str]
    r"""The name of the recipient bank / financial institution"""


class InternationalBankDetails(BaseModel):
    r"""Bank details required in the case of an international wire transfer"""

    additional_info: Optional[str] = None
    r"""Any additional information to be communicated to the recipient bank, such as intermediary banks to be used."""

    address: OptionalNullable[WireWithdrawalScheduleRecipientBankAddress] = UNSET
    r"""The address of the recipient bank / financial institution"""

    bank_name: Optional[str] = None
    r"""The name of the recipient bank / financial institution"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["additional_info", "address", "bank_name"]
        nullable_fields = ["address"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class RecipientBankTypedDict(TypedDict):
    r"""The recipient bank / financial institution"""

    bank_id: NotRequired[Nullable[BankIDTypedDict]]
    r"""An identifier that represents ABA routing number for domestic wire or BIC for foreign wire"""
    international_bank_details: NotRequired[Nullable[InternationalBankDetailsTypedDict]]
    r"""Bank details required in the case of an international wire transfer"""


class RecipientBank(BaseModel):
    r"""The recipient bank / financial institution"""

    bank_id: OptionalNullable[BankID] = UNSET
    r"""An identifier that represents ABA routing number for domestic wire or BIC for foreign wire"""

    international_bank_details: OptionalNullable[InternationalBankDetails] = UNSET
    r"""Bank details required in the case of an international wire transfer"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["bank_id", "international_bank_details"]
        nullable_fields = ["bank_id", "international_bank_details"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleRetirementDistributionFederalTaxWithholdingAmountTypedDict(
    TypedDict
):
    r"""Fixed USD amount to withhold for taxes."""

    value: NotRequired[str]
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleRetirementDistributionFederalTaxWithholdingAmount(
    BaseModel
):
    r"""Fixed USD amount to withhold for taxes."""

    value: Optional[str] = None
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalSchedulePercentageTypedDict(TypedDict):
    r"""Percentage of total disbursement amount to withhold for taxes."""

    value: NotRequired[str]
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalSchedulePercentage(BaseModel):
    r"""Percentage of total disbursement amount to withhold for taxes."""

    value: Optional[str] = None
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleFederalTaxWithholdingTypedDict(TypedDict):
    r"""The federal tax withholding."""

    amount: NotRequired[
        Nullable[
            WireWithdrawalScheduleRetirementDistributionFederalTaxWithholdingAmountTypedDict
        ]
    ]
    r"""Fixed USD amount to withhold for taxes."""
    percentage: NotRequired[Nullable[WireWithdrawalSchedulePercentageTypedDict]]
    r"""Percentage of total disbursement amount to withhold for taxes."""


class WireWithdrawalScheduleFederalTaxWithholding(BaseModel):
    r"""The federal tax withholding."""

    amount: OptionalNullable[
        WireWithdrawalScheduleRetirementDistributionFederalTaxWithholdingAmount
    ] = UNSET
    r"""Fixed USD amount to withhold for taxes."""

    percentage: OptionalNullable[WireWithdrawalSchedulePercentage] = UNSET
    r"""Percentage of total disbursement amount to withhold for taxes."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["amount", "percentage"]
        nullable_fields = ["amount", "percentage"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleRetirementDistributionAmountTypedDict(TypedDict):
    r"""Fixed USD amount to withhold for taxes."""

    value: NotRequired[str]
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleRetirementDistributionAmount(BaseModel):
    r"""Fixed USD amount to withhold for taxes."""

    value: Optional[str] = None
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleRetirementDistributionPercentageTypedDict(TypedDict):
    r"""Percentage of total disbursement amount to withhold for taxes."""

    value: NotRequired[str]
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleRetirementDistributionPercentage(BaseModel):
    r"""Percentage of total disbursement amount to withhold for taxes."""

    value: Optional[str] = None
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleStateTaxWithholdingTypedDict(TypedDict):
    r"""The state tax withholding."""

    amount: NotRequired[
        Nullable[WireWithdrawalScheduleRetirementDistributionAmountTypedDict]
    ]
    r"""Fixed USD amount to withhold for taxes."""
    percentage: NotRequired[
        Nullable[WireWithdrawalScheduleRetirementDistributionPercentageTypedDict]
    ]
    r"""Percentage of total disbursement amount to withhold for taxes."""


class WireWithdrawalScheduleStateTaxWithholding(BaseModel):
    r"""The state tax withholding."""

    amount: OptionalNullable[WireWithdrawalScheduleRetirementDistributionAmount] = UNSET
    r"""Fixed USD amount to withhold for taxes."""

    percentage: OptionalNullable[
        WireWithdrawalScheduleRetirementDistributionPercentage
    ] = UNSET
    r"""Percentage of total disbursement amount to withhold for taxes."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["amount", "percentage"]
        nullable_fields = ["amount", "percentage"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleType(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The type of retirement distribution."""

    TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED"
    NORMAL = "NORMAL"
    DISABILITY = "DISABILITY"
    SOSEPP = "SOSEPP"
    PREMATURE = "PREMATURE"
    DEATH = "DEATH"
    EXCESS_CONTRIBUTION_REMOVAL_BEFORE_TAX_DEADLINE = (
        "EXCESS_CONTRIBUTION_REMOVAL_BEFORE_TAX_DEADLINE"
    )
    EXCESS_CONTRIBUTION_REMOVAL_AFTER_TAX_DEADLINE = (
        "EXCESS_CONTRIBUTION_REMOVAL_AFTER_TAX_DEADLINE"
    )
    ROLLOVER_TO_QUALIFIED_PLAN = "ROLLOVER_TO_QUALIFIED_PLAN"
    ROLLOVER_TO_IRA = "ROLLOVER_TO_IRA"
    DISTRIBUTION_TRANSFER = "DISTRIBUTION_TRANSFER"
    RECHARACTERIZATION_PRIOR_YEAR = "RECHARACTERIZATION_PRIOR_YEAR"
    RECHARACTERIZATION_CURRENT_YEAR = "RECHARACTERIZATION_CURRENT_YEAR"
    DISTRIBUTION_CONVERSION = "DISTRIBUTION_CONVERSION"
    MANAGEMENT_FEE = "MANAGEMENT_FEE"
    PLAN_LOAN_401_K = "PLAN_LOAN_401K"
    PREMATURE_SIMPLE_IRA_LESS_THAN_2_YEARS = "PREMATURE_SIMPLE_IRA_LESS_THAN_2_YEARS"
    NORMAL_ROTH_IRA_GREATER_THAN_5_YEARS = "NORMAL_ROTH_IRA_GREATER_THAN_5_YEARS"


class WireWithdrawalScheduleRetirementDistributionTypedDict(TypedDict):
    r"""The distribution info for a retirement account"""

    federal_tax_withholding: NotRequired[
        Nullable[WireWithdrawalScheduleFederalTaxWithholdingTypedDict]
    ]
    r"""The federal tax withholding."""
    receiving_institution: NotRequired[str]
    r"""The institution receiving retirement funds when performing a transfer to an identical retirement account type at a different financial institution. This is required for check and wire withdrawals because we can't always identify the institution using the transfer instructions. For cash journals this value will default to \"Apex Clearing\", regardless of what is passed in here"""
    state_tax_withholding: NotRequired[
        Nullable[WireWithdrawalScheduleStateTaxWithholdingTypedDict]
    ]
    r"""The state tax withholding."""
    state_withholding_waiver: NotRequired[bool]
    r"""Whether or not this distribution has a state withholding waiver."""
    tax_year: NotRequired[int]
    r"""Tax year for which the distribution is applied."""
    type: NotRequired[WireWithdrawalScheduleType]
    r"""The type of retirement distribution."""


class WireWithdrawalScheduleRetirementDistribution(BaseModel):
    r"""The distribution info for a retirement account"""

    federal_tax_withholding: OptionalNullable[
        WireWithdrawalScheduleFederalTaxWithholding
    ] = UNSET
    r"""The federal tax withholding."""

    receiving_institution: Optional[str] = None
    r"""The institution receiving retirement funds when performing a transfer to an identical retirement account type at a different financial institution. This is required for check and wire withdrawals because we can't always identify the institution using the transfer instructions. For cash journals this value will default to \"Apex Clearing\", regardless of what is passed in here"""

    state_tax_withholding: OptionalNullable[
        WireWithdrawalScheduleStateTaxWithholding
    ] = UNSET
    r"""The state tax withholding."""

    state_withholding_waiver: Optional[bool] = None
    r"""Whether or not this distribution has a state withholding waiver."""

    tax_year: Optional[int] = None
    r"""Tax year for which the distribution is applied."""

    type: Annotated[
        Optional[WireWithdrawalScheduleType], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The type of retirement distribution."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "federal_tax_withholding",
            "receiving_institution",
            "state_tax_withholding",
            "state_withholding_waiver",
            "tax_year",
            "type",
        ]
        nullable_fields = ["federal_tax_withholding", "state_tax_withholding"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleAmountTypedDict(TypedDict):
    r"""A cash amount in the format of decimal value (mutually exclusive with 'full_disbursement')"""

    value: NotRequired[str]
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleAmount(BaseModel):
    r"""A cash amount in the format of decimal value (mutually exclusive with 'full_disbursement')"""

    value: Optional[str] = None
    r"""The decimal value, as a string; Refer to [Google’s Decimal type protocol buffer](https://github.com/googleapis/googleapis/blob/40203ca1880849480bbff7b8715491060bbccdf1/google/type/decimal.proto#L33) for details"""


class WireWithdrawalScheduleStartDateTypedDict(TypedDict):
    r"""The schedule start date"""

    day: NotRequired[int]
    r"""Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant."""
    month: NotRequired[int]
    r"""Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day."""
    year: NotRequired[int]
    r"""Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year."""


class WireWithdrawalScheduleStartDate(BaseModel):
    r"""The schedule start date"""

    day: Optional[int] = None
    r"""Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant."""

    month: Optional[int] = None
    r"""Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day."""

    year: Optional[int] = None
    r"""Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year."""


class WireWithdrawalScheduleState(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The state of the represented schedule"""

    ACTIVE = "ACTIVE"
    CANCELED = "CANCELED"
    COMPLETED = "COMPLETED"


class WireWithdrawalScheduleTimeUnit(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The time unit used to calculate the interval between transfers. The time period between transfers in a scheduled series is the unit of time times the multiplier"""

    DAY = "DAY"
    WEEK = "WEEK"
    MONTH = "MONTH"


class WireWithdrawalScheduleSchedulePropertiesTypedDict(TypedDict):
    r"""Common schedule properties"""

    occurrences: NotRequired[int]
    r"""The number of occurrences (empty or 0 indicates unlimited occurrences)"""
    start_date: NotRequired[Nullable[WireWithdrawalScheduleStartDateTypedDict]]
    r"""The schedule start date"""
    state: NotRequired[WireWithdrawalScheduleState]
    r"""The state of the represented schedule"""
    time_unit: NotRequired[WireWithdrawalScheduleTimeUnit]
    r"""The time unit used to calculate the interval between transfers. The time period between transfers in a scheduled series is the unit of time times the multiplier"""
    unit_multiplier: NotRequired[int]
    r"""The multiplier used to determine the length of the interval between transfers. The time period between transfers in a scheduled series is the unit of time times the multiplier"""


class WireWithdrawalScheduleScheduleProperties(BaseModel):
    r"""Common schedule properties"""

    occurrences: Optional[int] = None
    r"""The number of occurrences (empty or 0 indicates unlimited occurrences)"""

    start_date: OptionalNullable[WireWithdrawalScheduleStartDate] = UNSET
    r"""The schedule start date"""

    state: Annotated[
        Optional[WireWithdrawalScheduleState], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The state of the represented schedule"""

    time_unit: Annotated[
        Optional[WireWithdrawalScheduleTimeUnit],
        PlainValidator(validate_open_enum(False)),
    ] = None
    r"""The time unit used to calculate the interval between transfers. The time period between transfers in a scheduled series is the unit of time times the multiplier"""

    unit_multiplier: Optional[int] = None
    r"""The multiplier used to determine the length of the interval between transfers. The time period between transfers in a scheduled series is the unit of time times the multiplier"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "occurrences",
            "start_date",
            "state",
            "time_unit",
            "unit_multiplier",
        ]
        nullable_fields = ["start_date"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleScheduleDetailsTypedDict(TypedDict):
    r"""The transfer schedule details"""

    amount: NotRequired[Nullable[WireWithdrawalScheduleAmountTypedDict]]
    r"""A cash amount in the format of decimal value (mutually exclusive with 'full_disbursement')"""
    client_schedule_id: NotRequired[str]
    r"""External identifier supplied by the API caller. Each request must have a unique pairing of client_schedule_id and account"""
    full_disbursement: NotRequired[bool]
    r"""Flag to indicate a full disbursement transfer (mutually exclusive with 'amount')"""
    schedule_properties: NotRequired[
        Nullable[WireWithdrawalScheduleSchedulePropertiesTypedDict]
    ]
    r"""Common schedule properties"""


class WireWithdrawalScheduleScheduleDetails(BaseModel):
    r"""The transfer schedule details"""

    amount: OptionalNullable[WireWithdrawalScheduleAmount] = UNSET
    r"""A cash amount in the format of decimal value (mutually exclusive with 'full_disbursement')"""

    client_schedule_id: Optional[str] = None
    r"""External identifier supplied by the API caller. Each request must have a unique pairing of client_schedule_id and account"""

    full_disbursement: Optional[bool] = None
    r"""Flag to indicate a full disbursement transfer (mutually exclusive with 'amount')"""

    schedule_properties: OptionalNullable[
        WireWithdrawalScheduleScheduleProperties
    ] = UNSET
    r"""Common schedule properties"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "amount",
            "client_schedule_id",
            "full_disbursement",
            "schedule_properties",
        ]
        nullable_fields = ["amount", "schedule_properties"]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m


class WireWithdrawalScheduleTypedDict(TypedDict):
    r"""A withdrawal transfer schedule using the Wire mechanism"""

    beneficiary: NotRequired[Nullable[WireWithdrawalScheduleBeneficiaryTypedDict]]
    r"""The beneficiary of the wire withdrawal"""
    intermediary: NotRequired[Nullable[IntermediaryTypedDict]]
    r"""The intermediary party"""
    name: NotRequired[str]
    r"""The name of the Wire Withdrawal transfer schedule"""
    recipient_bank: NotRequired[Nullable[RecipientBankTypedDict]]
    r"""The recipient bank / financial institution"""
    retirement_distribution: NotRequired[
        Nullable[WireWithdrawalScheduleRetirementDistributionTypedDict]
    ]
    r"""The distribution info for a retirement account"""
    schedule_details: NotRequired[
        Nullable[WireWithdrawalScheduleScheduleDetailsTypedDict]
    ]
    r"""The transfer schedule details"""


class WireWithdrawalSchedule(BaseModel):
    r"""A withdrawal transfer schedule using the Wire mechanism"""

    beneficiary: OptionalNullable[WireWithdrawalScheduleBeneficiary] = UNSET
    r"""The beneficiary of the wire withdrawal"""

    intermediary: OptionalNullable[Intermediary] = UNSET
    r"""The intermediary party"""

    name: Optional[str] = None
    r"""The name of the Wire Withdrawal transfer schedule"""

    recipient_bank: OptionalNullable[RecipientBank] = UNSET
    r"""The recipient bank / financial institution"""

    retirement_distribution: OptionalNullable[
        WireWithdrawalScheduleRetirementDistribution
    ] = UNSET
    r"""The distribution info for a retirement account"""

    schedule_details: OptionalNullable[WireWithdrawalScheduleScheduleDetails] = UNSET
    r"""The transfer schedule details"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "beneficiary",
            "intermediary",
            "name",
            "recipient_bank",
            "retirement_distribution",
            "schedule_details",
        ]
        nullable_fields = [
            "beneficiary",
            "intermediary",
            "recipient_bank",
            "retirement_distribution",
            "schedule_details",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in self.model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            serialized.pop(k, None)

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m
