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

from __future__ import annotations
from .currency import Currency
from .linkedcustomer import LinkedCustomer, LinkedCustomerTypedDict
from .linkeddepartment import LinkedDepartment, LinkedDepartmentTypedDict
from .linkedexpensecategory import LinkedExpenseCategory, LinkedExpenseCategoryTypedDict
from .linkedledgeraccount import LinkedLedgerAccount, LinkedLedgerAccountTypedDict
from .linkedlocation import LinkedLocation, LinkedLocationTypedDict
from .linkedtaxrate import LinkedTaxRate, LinkedTaxRateTypedDict
from .linkedtrackingcategory import (
    LinkedTrackingCategory,
    LinkedTrackingCategoryTypedDict,
)
from apideck_unify import models
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 pydantic import field_serializer, model_serializer
from pydantic.functional_validators import PlainValidator
from typing import List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class ExpenseReportLineItemTypedDict(TypedDict):
    amount: float
    r"""The amount of the expense line item."""
    id: NotRequired[str]
    r"""A unique identifier for an object."""
    line_number: NotRequired[Nullable[int]]
    r"""Line number of the resource"""
    expense_category: NotRequired[LinkedExpenseCategoryTypedDict]
    r"""The expense category this entity is linked to."""
    account: NotRequired[Nullable[LinkedLedgerAccountTypedDict]]
    description: NotRequired[Nullable[str]]
    r"""The description of the expense line item."""
    quantity: NotRequired[Nullable[float]]
    unit_price: NotRequired[Nullable[float]]
    tax_rate: NotRequired[LinkedTaxRateTypedDict]
    tax_amount: NotRequired[Nullable[float]]
    r"""Tax amount"""
    total_amount: NotRequired[Nullable[float]]
    r"""The total amount of the expense line item including tax."""
    transaction_date: NotRequired[Nullable[date]]
    r"""The date of the individual expense."""
    billable: NotRequired[Nullable[bool]]
    r"""Whether the expense is billable to a customer."""
    reimbursable: NotRequired[Nullable[bool]]
    r"""Whether the expense is reimbursable to the employee."""
    customer: NotRequired[Nullable[LinkedCustomerTypedDict]]
    r"""The customer this entity is linked to."""
    department: NotRequired[Nullable[LinkedDepartmentTypedDict]]
    location: NotRequired[Nullable[LinkedLocationTypedDict]]
    tracking_categories: NotRequired[
        Nullable[List[Nullable[LinkedTrackingCategoryTypedDict]]]
    ]
    r"""A list of linked tracking categories."""
    receipt_url: NotRequired[Nullable[str]]
    r"""URL to the receipt or attachment for this expense line."""
    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)."""
    updated_by: NotRequired[Nullable[str]]
    r"""The user who last updated the object."""
    created_by: NotRequired[Nullable[str]]
    r"""The user who created 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."""


class ExpenseReportLineItem(BaseModel):
    amount: float
    r"""The amount of the expense line item."""

    id: Optional[str] = None
    r"""A unique identifier for an object."""

    line_number: OptionalNullable[int] = UNSET
    r"""Line number of the resource"""

    expense_category: Optional[LinkedExpenseCategory] = None
    r"""The expense category this entity is linked to."""

    account: OptionalNullable[LinkedLedgerAccount] = UNSET

    description: OptionalNullable[str] = UNSET
    r"""The description of the expense line item."""

    quantity: OptionalNullable[float] = UNSET

    unit_price: OptionalNullable[float] = UNSET

    tax_rate: Optional[LinkedTaxRate] = None

    tax_amount: OptionalNullable[float] = UNSET
    r"""Tax amount"""

    total_amount: OptionalNullable[float] = UNSET
    r"""The total amount of the expense line item including tax."""

    transaction_date: OptionalNullable[date] = UNSET
    r"""The date of the individual expense."""

    billable: OptionalNullable[bool] = UNSET
    r"""Whether the expense is billable to a customer."""

    reimbursable: OptionalNullable[bool] = UNSET
    r"""Whether the expense is reimbursable to the employee."""

    customer: OptionalNullable[LinkedCustomer] = UNSET
    r"""The customer this entity is linked to."""

    department: OptionalNullable[LinkedDepartment] = UNSET

    location: OptionalNullable[LinkedLocation] = UNSET

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

    receipt_url: OptionalNullable[str] = UNSET
    r"""URL to the receipt or attachment for this expense line."""

    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)."""

    updated_by: OptionalNullable[str] = UNSET
    r"""The user who last updated the object."""

    created_by: OptionalNullable[str] = UNSET
    r"""The user who created 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."""

    @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",
            "line_number",
            "expense_category",
            "account",
            "description",
            "quantity",
            "unit_price",
            "tax_rate",
            "tax_amount",
            "total_amount",
            "transaction_date",
            "billable",
            "reimbursable",
            "customer",
            "department",
            "location",
            "tracking_categories",
            "receipt_url",
            "currency",
            "updated_by",
            "created_by",
            "updated_at",
            "created_at",
        ]
        nullable_fields = [
            "line_number",
            "account",
            "description",
            "quantity",
            "unit_price",
            "tax_amount",
            "total_amount",
            "transaction_date",
            "billable",
            "reimbursable",
            "customer",
            "department",
            "location",
            "tracking_categories",
            "receipt_url",
            "currency",
            "updated_by",
            "created_by",
            "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
