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

from __future__ import annotations
from .address import Address, AddressTypedDict
from .bankaccount import BankAccount, BankAccountTypedDict
from .currency import Currency
from .customfield import CustomField, CustomFieldTypedDict
from .email import Email, EmailTypedDict
from .gender import Gender
from .linkeddepartment import LinkedDepartment, LinkedDepartmentTypedDict
from .linkeddepartment_input import (
    LinkedDepartmentInput,
    LinkedDepartmentInputTypedDict,
)
from .linkedlocation import LinkedLocation, LinkedLocationTypedDict
from .linkedlocation_input import LinkedLocationInput, LinkedLocationInputTypedDict
from .linkedsubsidiary import LinkedSubsidiary, LinkedSubsidiaryTypedDict
from .linkedsubsidiary_input import (
    LinkedSubsidiaryInput,
    LinkedSubsidiaryInputTypedDict,
)
from .linkedtrackingcategory import (
    LinkedTrackingCategory,
    LinkedTrackingCategoryTypedDict,
)
from .passthroughbody import PassThroughBody, PassThroughBodyTypedDict
from .phonenumber import PhoneNumber, PhoneNumberTypedDict
from apideck_unify import models, utils
from apideck_unify.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from apideck_unify.utils import validate_open_enum
from datetime import date, datetime
from enum import Enum
from pydantic import field_serializer, model_serializer
from pydantic.functional_validators import PlainValidator
from typing import Any, Dict, List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class EmployeeStatus(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The status of the employee."""

    ACTIVE = "active"
    INACTIVE = "inactive"
    TERMINATED = "terminated"


class AccountingEmployeeManagerTypedDict(TypedDict):
    r"""The manager of the employee."""

    id: NotRequired[str]
    r"""A unique identifier for the manager."""
    name: NotRequired[Nullable[str]]
    r"""The name of the manager."""


class AccountingEmployeeManager(BaseModel):
    r"""The manager of the employee."""

    id: Optional[str] = None
    r"""A unique identifier for the manager."""

    name: OptionalNullable[str] = UNSET
    r"""The name of the manager."""

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

        serialized = handler(self)

        m = {}

        for n, f in type(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 AccountingEmployeeTypedDict(TypedDict):
    id: NotRequired[str]
    r"""A unique identifier for an object."""
    downstream_id: NotRequired[Nullable[str]]
    r"""The third-party API ID of original entity"""
    display_id: NotRequired[Nullable[str]]
    r"""Id to be displayed."""
    first_name: NotRequired[Nullable[str]]
    r"""The first name of the employee."""
    last_name: NotRequired[Nullable[str]]
    r"""The last name of the employee."""
    display_name: NotRequired[Nullable[str]]
    r"""The display name of the employee."""
    emails: NotRequired[List[EmailTypedDict]]
    r"""Email addresses of the employee."""
    employee_number: NotRequired[Nullable[str]]
    r"""The employee number or identifier."""
    job_title: NotRequired[Nullable[str]]
    r"""The job title of the employee."""
    status: NotRequired[Nullable[EmployeeStatus]]
    r"""The status of the employee."""
    is_contractor: NotRequired[Nullable[bool]]
    r"""Whether the employee is a contractor."""
    department: NotRequired[Nullable[LinkedDepartmentTypedDict]]
    location: NotRequired[Nullable[LinkedLocationTypedDict]]
    manager: NotRequired[AccountingEmployeeManagerTypedDict]
    r"""The manager of the employee."""
    hire_date: NotRequired[Nullable[date]]
    r"""The date the employee was hired."""
    termination_date: NotRequired[Nullable[date]]
    r"""The date the employee was terminated."""
    gender: NotRequired[Nullable[Gender]]
    r"""The gender represents the gender identity of a person."""
    birth_date: NotRequired[Nullable[date]]
    r"""The date of birth of the employee."""
    subsidiary: NotRequired[Nullable[LinkedSubsidiaryTypedDict]]
    tracking_categories: NotRequired[
        Nullable[List[Nullable[LinkedTrackingCategoryTypedDict]]]
    ]
    r"""A list of linked tracking categories."""
    currency: NotRequired[Nullable[Currency]]
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""
    notes: NotRequired[Nullable[str]]
    r"""Notes about the employee."""
    addresses: NotRequired[List[AddressTypedDict]]
    r"""Addresses of the employee."""
    phone_numbers: NotRequired[List[PhoneNumberTypedDict]]
    r"""Phone numbers of the employee."""
    bank_account: NotRequired[BankAccountTypedDict]
    custom_fields: NotRequired[List[CustomFieldTypedDict]]
    custom_mappings: NotRequired[Nullable[Dict[str, Any]]]
    r"""When custom mappings are configured on the resource, the result is included here."""
    row_version: NotRequired[Nullable[str]]
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""
    updated_at: NotRequired[Nullable[datetime]]
    r"""The date and time when the object was last updated."""
    created_at: NotRequired[Nullable[datetime]]
    r"""The date and time when the object was created."""
    pass_through: NotRequired[List[PassThroughBodyTypedDict]]
    r"""The pass_through property allows passing service-specific, custom data or structured modifications in request body when creating or updating resources."""


class AccountingEmployee(BaseModel):
    id: Optional[str] = None
    r"""A unique identifier for an object."""

    downstream_id: OptionalNullable[str] = UNSET
    r"""The third-party API ID of original entity"""

    display_id: OptionalNullable[str] = UNSET
    r"""Id to be displayed."""

    first_name: OptionalNullable[str] = UNSET
    r"""The first name of the employee."""

    last_name: OptionalNullable[str] = UNSET
    r"""The last name of the employee."""

    display_name: OptionalNullable[str] = UNSET
    r"""The display name of the employee."""

    emails: Optional[List[Email]] = None
    r"""Email addresses of the employee."""

    employee_number: OptionalNullable[str] = UNSET
    r"""The employee number or identifier."""

    job_title: OptionalNullable[str] = UNSET
    r"""The job title of the employee."""

    status: Annotated[
        OptionalNullable[EmployeeStatus], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""The status of the employee."""

    is_contractor: OptionalNullable[bool] = UNSET
    r"""Whether the employee is a contractor."""

    department: OptionalNullable[LinkedDepartment] = UNSET

    location: OptionalNullable[LinkedLocation] = UNSET

    manager: Optional[AccountingEmployeeManager] = None
    r"""The manager of the employee."""

    hire_date: OptionalNullable[date] = UNSET
    r"""The date the employee was hired."""

    termination_date: OptionalNullable[date] = UNSET
    r"""The date the employee was terminated."""

    gender: Annotated[
        OptionalNullable[Gender], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""The gender represents the gender identity of a person."""

    birth_date: OptionalNullable[date] = UNSET
    r"""The date of birth of the employee."""

    subsidiary: OptionalNullable[LinkedSubsidiary] = UNSET

    tracking_categories: OptionalNullable[List[Nullable[LinkedTrackingCategory]]] = (
        UNSET
    )
    r"""A list of linked tracking categories."""

    currency: Annotated[
        OptionalNullable[Currency], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""

    notes: OptionalNullable[str] = UNSET
    r"""Notes about the employee."""

    addresses: Optional[List[Address]] = None
    r"""Addresses of the employee."""

    phone_numbers: Optional[List[PhoneNumber]] = None
    r"""Phone numbers of the employee."""

    bank_account: Optional[BankAccount] = None

    custom_fields: Optional[List[CustomField]] = None

    custom_mappings: OptionalNullable[Dict[str, Any]] = UNSET
    r"""When custom mappings are configured on the resource, the result is included here."""

    row_version: OptionalNullable[str] = UNSET
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""

    updated_at: OptionalNullable[datetime] = UNSET
    r"""The date and time when the object was last updated."""

    created_at: OptionalNullable[datetime] = UNSET
    r"""The date and time when the object was created."""

    pass_through: Optional[List[PassThroughBody]] = None
    r"""The pass_through property allows passing service-specific, custom data or structured modifications in request body when creating or updating resources."""

    @field_serializer("status")
    def serialize_status(self, value):
        if isinstance(value, str):
            try:
                return models.EmployeeStatus(value)
            except ValueError:
                return value
        return value

    @field_serializer("gender")
    def serialize_gender(self, value):
        if isinstance(value, str):
            try:
                return models.Gender(value)
            except ValueError:
                return value
        return value

    @field_serializer("currency")
    def serialize_currency(self, value):
        if isinstance(value, str):
            try:
                return models.Currency(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "id",
            "downstream_id",
            "display_id",
            "first_name",
            "last_name",
            "display_name",
            "emails",
            "employee_number",
            "job_title",
            "status",
            "is_contractor",
            "department",
            "location",
            "manager",
            "hire_date",
            "termination_date",
            "gender",
            "birth_date",
            "subsidiary",
            "tracking_categories",
            "currency",
            "notes",
            "addresses",
            "phone_numbers",
            "bank_account",
            "custom_fields",
            "custom_mappings",
            "row_version",
            "updated_at",
            "created_at",
            "pass_through",
        ]
        nullable_fields = [
            "downstream_id",
            "display_id",
            "first_name",
            "last_name",
            "display_name",
            "employee_number",
            "job_title",
            "status",
            "is_contractor",
            "department",
            "location",
            "hire_date",
            "termination_date",
            "gender",
            "birth_date",
            "subsidiary",
            "tracking_categories",
            "currency",
            "notes",
            "custom_mappings",
            "row_version",
            "updated_at",
            "created_at",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(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 AccountingEmployeeInputTypedDict(TypedDict):
    display_id: NotRequired[Nullable[str]]
    r"""Id to be displayed."""
    first_name: NotRequired[Nullable[str]]
    r"""The first name of the employee."""
    last_name: NotRequired[Nullable[str]]
    r"""The last name of the employee."""
    display_name: NotRequired[Nullable[str]]
    r"""The display name of the employee."""
    emails: NotRequired[List[EmailTypedDict]]
    r"""Email addresses of the employee."""
    employee_number: NotRequired[Nullable[str]]
    r"""The employee number or identifier."""
    job_title: NotRequired[Nullable[str]]
    r"""The job title of the employee."""
    status: NotRequired[Nullable[EmployeeStatus]]
    r"""The status of the employee."""
    is_contractor: NotRequired[Nullable[bool]]
    r"""Whether the employee is a contractor."""
    department: NotRequired[Nullable[LinkedDepartmentInputTypedDict]]
    location: NotRequired[Nullable[LinkedLocationInputTypedDict]]
    manager: NotRequired[AccountingEmployeeManagerTypedDict]
    r"""The manager of the employee."""
    hire_date: NotRequired[Nullable[date]]
    r"""The date the employee was hired."""
    termination_date: NotRequired[Nullable[date]]
    r"""The date the employee was terminated."""
    gender: NotRequired[Nullable[Gender]]
    r"""The gender represents the gender identity of a person."""
    birth_date: NotRequired[Nullable[date]]
    r"""The date of birth of the employee."""
    subsidiary: NotRequired[Nullable[LinkedSubsidiaryInputTypedDict]]
    tracking_categories: NotRequired[
        Nullable[List[Nullable[LinkedTrackingCategoryTypedDict]]]
    ]
    r"""A list of linked tracking categories."""
    currency: NotRequired[Nullable[Currency]]
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""
    notes: NotRequired[Nullable[str]]
    r"""Notes about the employee."""
    addresses: NotRequired[List[AddressTypedDict]]
    r"""Addresses of the employee."""
    phone_numbers: NotRequired[List[PhoneNumberTypedDict]]
    r"""Phone numbers of the employee."""
    bank_account: NotRequired[BankAccountTypedDict]
    custom_fields: NotRequired[List[CustomFieldTypedDict]]
    row_version: NotRequired[Nullable[str]]
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""
    pass_through: NotRequired[List[PassThroughBodyTypedDict]]
    r"""The pass_through property allows passing service-specific, custom data or structured modifications in request body when creating or updating resources."""


class AccountingEmployeeInput(BaseModel):
    display_id: OptionalNullable[str] = UNSET
    r"""Id to be displayed."""

    first_name: OptionalNullable[str] = UNSET
    r"""The first name of the employee."""

    last_name: OptionalNullable[str] = UNSET
    r"""The last name of the employee."""

    display_name: OptionalNullable[str] = UNSET
    r"""The display name of the employee."""

    emails: Optional[List[Email]] = None
    r"""Email addresses of the employee."""

    employee_number: OptionalNullable[str] = UNSET
    r"""The employee number or identifier."""

    job_title: OptionalNullable[str] = UNSET
    r"""The job title of the employee."""

    status: Annotated[
        OptionalNullable[EmployeeStatus], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""The status of the employee."""

    is_contractor: OptionalNullable[bool] = UNSET
    r"""Whether the employee is a contractor."""

    department: OptionalNullable[LinkedDepartmentInput] = UNSET

    location: OptionalNullable[LinkedLocationInput] = UNSET

    manager: Optional[AccountingEmployeeManager] = None
    r"""The manager of the employee."""

    hire_date: OptionalNullable[date] = UNSET
    r"""The date the employee was hired."""

    termination_date: OptionalNullable[date] = UNSET
    r"""The date the employee was terminated."""

    gender: Annotated[
        OptionalNullable[Gender], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""The gender represents the gender identity of a person."""

    birth_date: OptionalNullable[date] = UNSET
    r"""The date of birth of the employee."""

    subsidiary: OptionalNullable[LinkedSubsidiaryInput] = UNSET

    tracking_categories: OptionalNullable[List[Nullable[LinkedTrackingCategory]]] = (
        UNSET
    )
    r"""A list of linked tracking categories."""

    currency: Annotated[
        OptionalNullable[Currency], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""Indicates the associated currency for an amount of money. Values correspond to [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)."""

    notes: OptionalNullable[str] = UNSET
    r"""Notes about the employee."""

    addresses: Optional[List[Address]] = None
    r"""Addresses of the employee."""

    phone_numbers: Optional[List[PhoneNumber]] = None
    r"""Phone numbers of the employee."""

    bank_account: Optional[BankAccount] = None

    custom_fields: Optional[List[CustomField]] = None

    row_version: OptionalNullable[str] = UNSET
    r"""A binary value used to detect updates to a object and prevent data conflicts. It is incremented each time an update is made to the object."""

    pass_through: Optional[List[PassThroughBody]] = None
    r"""The pass_through property allows passing service-specific, custom data or structured modifications in request body when creating or updating resources."""

    @field_serializer("status")
    def serialize_status(self, value):
        if isinstance(value, str):
            try:
                return models.EmployeeStatus(value)
            except ValueError:
                return value
        return value

    @field_serializer("gender")
    def serialize_gender(self, value):
        if isinstance(value, str):
            try:
                return models.Gender(value)
            except ValueError:
                return value
        return value

    @field_serializer("currency")
    def serialize_currency(self, value):
        if isinstance(value, str):
            try:
                return models.Currency(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "display_id",
            "first_name",
            "last_name",
            "display_name",
            "emails",
            "employee_number",
            "job_title",
            "status",
            "is_contractor",
            "department",
            "location",
            "manager",
            "hire_date",
            "termination_date",
            "gender",
            "birth_date",
            "subsidiary",
            "tracking_categories",
            "currency",
            "notes",
            "addresses",
            "phone_numbers",
            "bank_account",
            "custom_fields",
            "row_version",
            "pass_through",
        ]
        nullable_fields = [
            "display_id",
            "first_name",
            "last_name",
            "display_name",
            "employee_number",
            "job_title",
            "status",
            "is_contractor",
            "department",
            "location",
            "hire_date",
            "termination_date",
            "gender",
            "birth_date",
            "subsidiary",
            "tracking_categories",
            "currency",
            "notes",
            "row_version",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

        for n, f in type(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
