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

from __future__ import annotations
from .garnishment_child_support import (
    GarnishmentChildSupport,
    GarnishmentChildSupportTypedDict,
)
from enum import Enum
from gusto_embedded.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from pydantic import model_serializer
from typing import Optional
from typing_extensions import NotRequired, TypedDict


class GarnishmentType(str, Enum):
    r"""The specific type of garnishment for court ordered garnishments."""

    CHILD_SUPPORT = "child_support"
    FEDERAL_TAX_LIEN = "federal_tax_lien"
    STATE_TAX_LIEN = "state_tax_lien"
    STUDENT_LOAN = "student_loan"
    CREDITOR_GARNISHMENT = "creditor_garnishment"
    FEDERAL_LOAN = "federal_loan"
    OTHER_GARNISHMENT = "other_garnishment"


class GarnishmentTypedDict(TypedDict):
    r"""Garnishments, or employee deductions, are fixed amounts or percentages deducted from an employee’s pay. They can be deducted a specific number of times or on a recurring basis. Garnishments can also have maximum deductions on a yearly or per-pay-period bases. Common uses for garnishments are court-ordered payments for child support or back taxes. Some companies provide loans to their employees that are repaid via garnishments."""

    uuid: str
    r"""The UUID of the garnishment in Gusto."""
    version: NotRequired[str]
    r"""The current version of the object. See the [versioning guide](https://docs.gusto.com/embedded-payroll/docs/idempotency) for information on how to use this field."""
    employee_uuid: NotRequired[str]
    r"""The UUID of the employee to which this garnishment belongs."""
    active: NotRequired[bool]
    r"""Whether or not this garnishment is currently active."""
    amount: NotRequired[str]
    r"""The amount of the garnishment. Either a percentage or a fixed dollar amount. Represented as a float, e.g. \"8.00\"."""
    description: NotRequired[str]
    r"""The description of the garnishment."""
    court_ordered: NotRequired[bool]
    r"""Whether the garnishment is court ordered."""
    times: NotRequired[Nullable[int]]
    r"""The number of times to apply the garnishment. Ignored if recurring is true."""
    recurring: NotRequired[bool]
    r"""Whether the garnishment should recur indefinitely."""
    annual_maximum: NotRequired[Nullable[str]]
    r"""The maximum deduction per annum. A null value indicates no maximum. Represented as a float, e.g. \"200.00\"."""
    pay_period_maximum: NotRequired[Nullable[str]]
    r"""The maximum deduction per pay period. A null value indicates no maximum. Represented as a float, e.g. \"16.00\"."""
    deduct_as_percentage: NotRequired[bool]
    r"""Whether the amount should be treated as a percentage to be deducted per pay period."""
    garnishment_type: NotRequired[Nullable[GarnishmentType]]
    r"""The specific type of garnishment for court ordered garnishments."""
    child_support: NotRequired[Nullable[GarnishmentChildSupportTypedDict]]
    r"""Additional child support order details"""


class Garnishment(BaseModel):
    r"""Garnishments, or employee deductions, are fixed amounts or percentages deducted from an employee’s pay. They can be deducted a specific number of times or on a recurring basis. Garnishments can also have maximum deductions on a yearly or per-pay-period bases. Common uses for garnishments are court-ordered payments for child support or back taxes. Some companies provide loans to their employees that are repaid via garnishments."""

    uuid: str
    r"""The UUID of the garnishment in Gusto."""

    version: Optional[str] = None
    r"""The current version of the object. See the [versioning guide](https://docs.gusto.com/embedded-payroll/docs/idempotency) for information on how to use this field."""

    employee_uuid: Optional[str] = None
    r"""The UUID of the employee to which this garnishment belongs."""

    active: Optional[bool] = True
    r"""Whether or not this garnishment is currently active."""

    amount: Optional[str] = None
    r"""The amount of the garnishment. Either a percentage or a fixed dollar amount. Represented as a float, e.g. \"8.00\"."""

    description: Optional[str] = None
    r"""The description of the garnishment."""

    court_ordered: Optional[bool] = None
    r"""Whether the garnishment is court ordered."""

    times: OptionalNullable[int] = None
    r"""The number of times to apply the garnishment. Ignored if recurring is true."""

    recurring: Optional[bool] = False
    r"""Whether the garnishment should recur indefinitely."""

    annual_maximum: OptionalNullable[str] = None
    r"""The maximum deduction per annum. A null value indicates no maximum. Represented as a float, e.g. \"200.00\"."""

    pay_period_maximum: OptionalNullable[str] = None
    r"""The maximum deduction per pay period. A null value indicates no maximum. Represented as a float, e.g. \"16.00\"."""

    deduct_as_percentage: Optional[bool] = False
    r"""Whether the amount should be treated as a percentage to be deducted per pay period."""

    garnishment_type: OptionalNullable[GarnishmentType] = UNSET
    r"""The specific type of garnishment for court ordered garnishments."""

    child_support: OptionalNullable[GarnishmentChildSupport] = UNSET
    r"""Additional child support order details"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "version",
            "employee_uuid",
            "active",
            "amount",
            "description",
            "court_ordered",
            "times",
            "recurring",
            "annual_maximum",
            "pay_period_maximum",
            "deduct_as_percentage",
            "garnishment_type",
            "child_support",
        ]
        nullable_fields = [
            "times",
            "annual_maximum",
            "pay_period_maximum",
            "garnishment_type",
            "child_support",
        ]
        null_default_fields = ["times", "annual_maximum", "pay_period_maximum"]

        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
