"""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
from pydantic import model_serializer
from pydantic.functional_validators import PlainValidator
from typing import Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class TransferScheduleSummaryAmountTypedDict(TypedDict):
    r"""A cash amount in the format of decimal value. An unset or empty value represents a 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 TransferScheduleSummaryAmount(BaseModel):
    r"""A cash amount in the format of decimal value. An unset or empty value represents a 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 TransferScheduleSummaryDirection(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""Flag indicating whether this is a deposit or withdrawal transfer"""

    DIRECTION_UNSPECIFIED = "DIRECTION_UNSPECIFIED"
    DEPOSIT = "DEPOSIT"
    WITHDRAWAL = "WITHDRAWAL"


class TransferScheduleSummaryMechanism(str, Enum):
    r"""The mechanism used for this transfer schedule"""

    ACH = "ACH"
    WIRE = "WIRE"


class TransferScheduleSummaryTemporalTaxYear(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""A temporal tax year value. This will always evaluate to a year based on the date the transfer was initiated."""

    TEMPORAL_TAX_YEAR_UNSPECIFIED = "TEMPORAL_TAX_YEAR_UNSPECIFIED"
    CURRENT_CALENDAR_YEAR = "CURRENT_CALENDAR_YEAR"
    MINIMUM_TAX_YEAR = "MINIMUM_TAX_YEAR"


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

    TYPE_UNSPECIFIED = "TYPE_UNSPECIFIED"
    REGULAR = "REGULAR"
    EMPLOYEE = "EMPLOYEE"
    EMPLOYER = "EMPLOYER"
    RECHARACTERIZATION = "RECHARACTERIZATION"
    ROLLOVER_60_DAY = "ROLLOVER_60_DAY"
    ROLLOVER_DIRECT = "ROLLOVER_DIRECT"
    TRANSFER = "TRANSFER"
    TRUSTEE_FEE = "TRUSTEE_FEE"
    CONVERSION = "CONVERSION"
    REPAYMENT = "REPAYMENT"


class TransferScheduleSummaryRetirementContributionTypedDict(TypedDict):
    r"""The contribution info for a retirement account"""

    tax_year: NotRequired[int]
    r"""An explicit tax year value. The current year is always valid; and the prior year is valid only before the tax deadline. Must be in \"YYYY\" format."""
    temporal_tax_year: NotRequired[TransferScheduleSummaryTemporalTaxYear]
    r"""A temporal tax year value. This will always evaluate to a year based on the date the transfer was initiated."""
    type: NotRequired[TransferScheduleSummaryType]
    r"""The type of retirement contribution."""


class TransferScheduleSummaryRetirementContribution(BaseModel):
    r"""The contribution info for a retirement account"""

    tax_year: Optional[int] = None
    r"""An explicit tax year value. The current year is always valid; and the prior year is valid only before the tax deadline. Must be in \"YYYY\" format."""

    temporal_tax_year: Annotated[
        Optional[TransferScheduleSummaryTemporalTaxYear],
        PlainValidator(validate_open_enum(False)),
    ] = None
    r"""A temporal tax year value. This will always evaluate to a year based on the date the transfer was initiated."""

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


class TransferScheduleSummaryRetirementDistributionAmountTypedDict(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 TransferScheduleSummaryRetirementDistributionAmount(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 TransferScheduleSummaryPercentageTypedDict(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 TransferScheduleSummaryPercentage(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 TransferScheduleSummaryFederalTaxWithholdingTypedDict(TypedDict):
    r"""The federal tax withholding."""

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


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

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

    percentage: OptionalNullable[TransferScheduleSummaryPercentage] = 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 TransferScheduleSummaryRetirementDistributionStateTaxWithholdingAmountTypedDict(
    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 TransferScheduleSummaryRetirementDistributionStateTaxWithholdingAmount(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 TransferScheduleSummaryRetirementDistributionPercentageTypedDict(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 TransferScheduleSummaryRetirementDistributionPercentage(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 TransferScheduleSummaryStateTaxWithholdingTypedDict(TypedDict):
    r"""The state tax withholding."""

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


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

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

    percentage: OptionalNullable[
        TransferScheduleSummaryRetirementDistributionPercentage
    ] = 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 TransferScheduleSummaryRetirementDistributionType(
    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 TransferScheduleSummaryRetirementDistributionTypedDict(TypedDict):
    r"""The distribution info for a retirement account"""

    federal_tax_withholding: NotRequired[
        Nullable[TransferScheduleSummaryFederalTaxWithholdingTypedDict]
    ]
    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[TransferScheduleSummaryStateTaxWithholdingTypedDict]
    ]
    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[TransferScheduleSummaryRetirementDistributionType]
    r"""The type of retirement distribution."""


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

    federal_tax_withholding: OptionalNullable[
        TransferScheduleSummaryFederalTaxWithholding
    ] = 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[
        TransferScheduleSummaryStateTaxWithholding
    ] = 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[TransferScheduleSummaryRetirementDistributionType],
        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 StartDateTypedDict(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 StartDate(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 TransferScheduleSummaryState(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The state of the represented schedule"""

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


class TransferScheduleSummaryTimeUnit(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 SchedulePropertiesTypedDict(TypedDict):
    r"""Common schedule properties"""

    occurrences: NotRequired[int]
    r"""The number of occurrences (empty or 0 indicates unlimited occurrences)"""
    start_date: NotRequired[Nullable[StartDateTypedDict]]
    r"""The schedule start date"""
    state: NotRequired[TransferScheduleSummaryState]
    r"""The state of the represented schedule"""
    time_unit: NotRequired[TransferScheduleSummaryTimeUnit]
    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 ScheduleProperties(BaseModel):
    r"""Common schedule properties"""

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

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

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

    time_unit: Annotated[
        Optional[TransferScheduleSummaryTimeUnit],
        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 TransferScheduleSummaryTypedDict(TypedDict):
    r"""A transfer schedule summary that contains all of the common properties a schedules across rails"""

    amount: NotRequired[Nullable[TransferScheduleSummaryAmountTypedDict]]
    r"""A cash amount in the format of decimal value. An unset or empty value represents a 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"""
    direction: NotRequired[TransferScheduleSummaryDirection]
    r"""Flag indicating whether this is a deposit or withdrawal transfer"""
    mechanism: NotRequired[TransferScheduleSummaryMechanism]
    r"""The mechanism used for this transfer schedule"""
    retirement_contribution: NotRequired[
        Nullable[TransferScheduleSummaryRetirementContributionTypedDict]
    ]
    r"""The contribution info for a retirement account"""
    retirement_distribution: NotRequired[
        Nullable[TransferScheduleSummaryRetirementDistributionTypedDict]
    ]
    r"""The distribution info for a retirement account"""
    schedule_properties: NotRequired[Nullable[SchedulePropertiesTypedDict]]
    r"""Common schedule properties"""
    transfer_schedule: NotRequired[str]
    r"""The name of the schedule resource this detail represents"""


class TransferScheduleSummary(BaseModel):
    r"""A transfer schedule summary that contains all of the common properties a schedules across rails"""

    amount: OptionalNullable[TransferScheduleSummaryAmount] = UNSET
    r"""A cash amount in the format of decimal value. An unset or empty value represents a 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"""

    direction: Annotated[
        Optional[TransferScheduleSummaryDirection],
        PlainValidator(validate_open_enum(False)),
    ] = None
    r"""Flag indicating whether this is a deposit or withdrawal transfer"""

    mechanism: Optional[TransferScheduleSummaryMechanism] = None
    r"""The mechanism used for this transfer schedule"""

    retirement_contribution: OptionalNullable[
        TransferScheduleSummaryRetirementContribution
    ] = UNSET
    r"""The contribution info for a retirement account"""

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

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

    transfer_schedule: Optional[str] = None
    r"""The name of the schedule resource this detail represents"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "amount",
            "client_schedule_id",
            "direction",
            "mechanism",
            "retirement_contribution",
            "retirement_distribution",
            "schedule_properties",
            "transfer_schedule",
        ]
        nullable_fields = [
            "amount",
            "retirement_contribution",
            "retirement_distribution",
            "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
