"""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 datetime import datetime
from enum import Enum
import pydantic
from pydantic import model_serializer
from pydantic.functional_validators import PlainValidator
from typing import Any, Dict, List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class WireWithdrawalAmountTypedDict(TypedDict):
    r"""A cash amount in the format of decimal value"""

    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 WireWithdrawalAmount(BaseModel):
    r"""A cash amount in the format of decimal value"""

    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 WireWithdrawalAddressTypedDict(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 WireWithdrawalAddress(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 WireWithdrawalBeneficiaryTypedDict(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[WireWithdrawalAddressTypedDict]]
    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 WireWithdrawalBeneficiary(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[WireWithdrawalAddress] = 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 WireWithdrawalIntermediaryAddressTypedDict(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 WireWithdrawalIntermediaryAddress(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 WireWithdrawalIntermediaryTypedDict(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[WireWithdrawalIntermediaryAddressTypedDict]]
    r"""The address of the intermediary party"""


class WireWithdrawalIntermediary(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[WireWithdrawalIntermediaryAddress] = 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 WireWithdrawalIraDistributionAmountTypedDict(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 WireWithdrawalIraDistributionAmount(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 WireWithdrawalPercentageTypedDict(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 WireWithdrawalPercentage(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 WireWithdrawalFederalTaxWithholdingTypedDict(TypedDict):
    r"""The federal tax withholding."""

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


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

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

    percentage: OptionalNullable[WireWithdrawalPercentage] = 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 WireWithdrawalIraDistributionStateTaxWithholdingAmountTypedDict(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 WireWithdrawalIraDistributionStateTaxWithholdingAmount(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 WireWithdrawalIraDistributionPercentageTypedDict(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 WireWithdrawalIraDistributionPercentage(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 WireWithdrawalStateTaxWithholdingTypedDict(TypedDict):
    r"""The state tax withholding."""

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


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

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

    percentage: OptionalNullable[WireWithdrawalIraDistributionPercentage] = 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 WireWithdrawalType(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 WireWithdrawalIraDistributionTypedDict(TypedDict):
    r"""IRA distribution details for withdrawal from retirement account"""

    federal_tax_withholding: NotRequired[
        Nullable[WireWithdrawalFederalTaxWithholdingTypedDict]
    ]
    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[WireWithdrawalStateTaxWithholdingTypedDict]
    ]
    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[WireWithdrawalType]
    r"""The type of retirement distribution."""


class WireWithdrawalIraDistribution(BaseModel):
    r"""IRA distribution details for withdrawal from retirement account"""

    federal_tax_withholding: OptionalNullable[
        WireWithdrawalFederalTaxWithholding
    ] = 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[WireWithdrawalStateTaxWithholding] = 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[WireWithdrawalType], 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 WireWithdrawalRecipientBankType(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The type of bank identifier specified"""

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


class WireWithdrawalBankIDTypedDict(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[WireWithdrawalRecipientBankType]
    r"""The type of bank identifier specified"""


class WireWithdrawalBankID(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[WireWithdrawalRecipientBankType],
        PlainValidator(validate_open_enum(False)),
    ] = None
    r"""The type of bank identifier specified"""


class WireWithdrawalRecipientBankAddressTypedDict(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 WireWithdrawalRecipientBankAddress(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 WireWithdrawalInternationalBankDetailsTypedDict(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[WireWithdrawalRecipientBankAddressTypedDict]]
    r"""The address of the recipient bank / financial institution"""
    bank_name: NotRequired[str]
    r"""The name of the recipient bank / financial institution"""


class WireWithdrawalInternationalBankDetails(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[WireWithdrawalRecipientBankAddress] = 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 WireWithdrawalRecipientBankTypedDict(TypedDict):
    r"""The recipient bank / financial institution"""

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


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

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

    international_bank_details: OptionalNullable[
        WireWithdrawalInternationalBankDetails
    ] = 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 WireWithdrawalStateState(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The high level state of a transfer, one of:
    - `PROCESSING` - The transfer is being processed and will be posted if successful.
    - `PENDING_REVIEW` - The transfer is pending review and will continue processing if approved.
    - `POSTED` - The transfer has been posted to the ledger and will be completed at the end of the processing window if not canceled first.
    - `COMPLETED` - The transfer has been batched and completed.
    - `REJECTED` - The transfer was rejected.
    - `CANCELED` - The transfer was canceled.
    - `RETURNED` - The transfer was returned.
    - `POSTPONED` - The transfer is postponed and will resume processing during the next processing window.
    """

    STATE_UNSPECIFIED = "STATE_UNSPECIFIED"
    PROCESSING = "PROCESSING"
    PENDING_REVIEW = "PENDING_REVIEW"
    POSTED = "POSTED"
    COMPLETED = "COMPLETED"
    REJECTED = "REJECTED"
    CANCELED = "CANCELED"
    RETURNED = "RETURNED"
    POSTPONED = "POSTPONED"


class WireWithdrawalStateTypedDict(TypedDict):
    r"""The current state of the wire withdrawal"""

    actor: NotRequired[str]
    r"""The user or service that triggered the state update."""
    message: NotRequired[str]
    r"""Additional description of the transfer state."""
    metadata: NotRequired[Nullable[Dict[str, Any]]]
    r"""Additional metadata relating to the transfer state. Included data depends on the state, e.g.:
    - Rejection reasons are included when the `state` is `REJECTED`
    - Reason and comment are included when `state` is `CANCELED`
    """
    state: NotRequired[WireWithdrawalStateState]
    r"""The high level state of a transfer, one of:
    - `PROCESSING` - The transfer is being processed and will be posted if successful.
    - `PENDING_REVIEW` - The transfer is pending review and will continue processing if approved.
    - `POSTED` - The transfer has been posted to the ledger and will be completed at the end of the processing window if not canceled first.
    - `COMPLETED` - The transfer has been batched and completed.
    - `REJECTED` - The transfer was rejected.
    - `CANCELED` - The transfer was canceled.
    - `RETURNED` - The transfer was returned.
    - `POSTPONED` - The transfer is postponed and will resume processing during the next processing window.
    """
    update_time: NotRequired[Nullable[datetime]]
    r"""The time of the state update."""


class WireWithdrawalState(BaseModel):
    r"""The current state of the wire withdrawal"""

    actor: Optional[str] = None
    r"""The user or service that triggered the state update."""

    message: Optional[str] = None
    r"""Additional description of the transfer state."""

    metadata: OptionalNullable[Dict[str, Any]] = UNSET
    r"""Additional metadata relating to the transfer state. Included data depends on the state, e.g.:
    - Rejection reasons are included when the `state` is `REJECTED`
    - Reason and comment are included when `state` is `CANCELED`
    """

    state: Annotated[
        Optional[WireWithdrawalStateState], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The high level state of a transfer, one of:
    - `PROCESSING` - The transfer is being processed and will be posted if successful.
    - `PENDING_REVIEW` - The transfer is pending review and will continue processing if approved.
    - `POSTED` - The transfer has been posted to the ledger and will be completed at the end of the processing window if not canceled first.
    - `COMPLETED` - The transfer has been batched and completed.
    - `REJECTED` - The transfer was rejected.
    - `CANCELED` - The transfer was canceled.
    - `RETURNED` - The transfer was returned.
    - `POSTPONED` - The transfer is postponed and will resume processing during the next processing window.
    """

    update_time: OptionalNullable[datetime] = UNSET
    r"""The time of the state update."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["actor", "message", "metadata", "state", "update_time"]
        nullable_fields = ["metadata", "update_time"]
        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 WireWithdrawalTypedDict(TypedDict):
    r"""A withdrawal transfer using the wire mechanism"""

    amount: NotRequired[Nullable[WireWithdrawalAmountTypedDict]]
    r"""A cash amount in the format of decimal value"""
    beneficiary: NotRequired[Nullable[WireWithdrawalBeneficiaryTypedDict]]
    r"""The beneficiary of the wire withdrawal"""
    client_transfer_id: NotRequired[str]
    r"""External identifier supplied by the API caller. Each request must have a unique pairing of client_transfer_id and account"""
    fed_reference_number: NotRequired[str]
    r"""The FedWire reference number for the withdrawal. Only set after the transfer is completed."""
    intermediary: NotRequired[Nullable[WireWithdrawalIntermediaryTypedDict]]
    r"""The intermediary party"""
    ira_distribution: NotRequired[Nullable[WireWithdrawalIraDistributionTypedDict]]
    r"""IRA distribution details for withdrawal from retirement account"""
    name: NotRequired[str]
    r"""The service generated name of the wire withdrawal"""
    recipient_bank: NotRequired[Nullable[WireWithdrawalRecipientBankTypedDict]]
    r"""The recipient bank / financial institution"""
    state: NotRequired[Nullable[WireWithdrawalStateTypedDict]]
    r"""The current state of the wire withdrawal"""


class WireWithdrawal(BaseModel):
    r"""A withdrawal transfer using the wire mechanism"""

    amount: OptionalNullable[WireWithdrawalAmount] = UNSET
    r"""A cash amount in the format of decimal value"""

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

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

    fed_reference_number: Optional[str] = None
    r"""The FedWire reference number for the withdrawal. Only set after the transfer is completed."""

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

    ira_distribution: OptionalNullable[WireWithdrawalIraDistribution] = UNSET
    r"""IRA distribution details for withdrawal from retirement account"""

    name: Optional[str] = None
    r"""The service generated name of the wire withdrawal"""

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

    state: OptionalNullable[WireWithdrawalState] = UNSET
    r"""The current state of the wire withdrawal"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "amount",
            "beneficiary",
            "client_transfer_id",
            "fed_reference_number",
            "intermediary",
            "ira_distribution",
            "name",
            "recipient_bank",
            "state",
        ]
        nullable_fields = [
            "amount",
            "beneficiary",
            "intermediary",
            "ira_distribution",
            "recipient_bank",
            "state",
        ]
        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
