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

from __future__ import annotations
from .address import Address, AddressTypedDict
from .allocation import Allocation, AllocationTypedDict
from .currency import Currency
from .customfield import CustomField, CustomFieldTypedDict
from .invoicelineitem import InvoiceLineItem, InvoiceLineItemTypedDict
from .linkedcustomer import LinkedCustomer, LinkedCustomerTypedDict
from .linkeddepartment import LinkedDepartment, LinkedDepartmentTypedDict
from .linkedledgeraccount import LinkedLedgerAccount, LinkedLedgerAccountTypedDict
from .linkedlocation import LinkedLocation, LinkedLocationTypedDict
from .linkedtrackingcategory import (
    LinkedTrackingCategory,
    LinkedTrackingCategoryTypedDict,
)
from .passthroughbody import PassThroughBody, PassThroughBodyTypedDict
from .refundstatus import RefundStatus
from .refundtype import RefundType
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 datetime
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 RefundTypedDict(TypedDict):
    id: str
    r"""Unique identifier representing the refund"""
    total_amount: Nullable[float]
    r"""The total amount of the transaction or record"""
    number: NotRequired[Nullable[str]]
    r"""Reference number for the refund."""
    customer: NotRequired[Nullable[LinkedCustomerTypedDict]]
    r"""The customer this entity is linked to."""
    company_id: NotRequired[Nullable[str]]
    r"""The company ID the transaction belongs to"""
    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)."""
    currency_rate: NotRequired[Nullable[float]]
    r"""Currency Exchange Rate at the time entity was recorded/generated."""
    tax_inclusive: NotRequired[Nullable[bool]]
    r"""Amounts are including tax"""
    sub_total: NotRequired[Nullable[float]]
    r"""Subtotal amount, normally before tax."""
    total_tax: NotRequired[Nullable[float]]
    r"""Total tax amount applied to this transaction."""
    refund_date: NotRequired[Nullable[datetime]]
    r"""The date of the refund - YYYY-MM-DDThh:mm:ss.sTZD"""
    status: NotRequired[RefundStatus]
    r"""Status of refund. Maps to: QBO (limited status), NetSuite CashRefund status, Sage Intacct state (draft/posted/voided), Zoho Books vis_state."""
    type: NotRequired[RefundType]
    r"""Type of refund. `refund_receipt` for itemized refunds with product/service lines and payment (QBO RefundReceipt, NetSuite CashRefund). `cash_refund` for cash-out refunds with GL distribution or allocations (Sage Intacct). `credit_note_refund` for refunds applied against a credit note (Zoho Books)."""
    payment_method: NotRequired[Nullable[str]]
    r"""Payment method used for the transaction, such as cash, credit card, bank transfer, or check"""
    payment_method_reference: NotRequired[Nullable[str]]
    r"""Optional reference message returned by payment method on processing"""
    payment_method_id: NotRequired[Nullable[str]]
    r"""A unique identifier for an object."""
    account: NotRequired[Nullable[LinkedLedgerAccountTypedDict]]
    line_items: NotRequired[List[InvoiceLineItemTypedDict]]
    r"""Line items for itemized refunds (type: refund_receipt). Used when the refund includes product/service details with quantities and pricing. Supported by QBO RefundReceipt and NetSuite CashRefund."""
    allocations: NotRequired[List[AllocationTypedDict]]
    r"""Allocations linking refund to existing documents (invoices, credit notes, overpayments). Used for credit_note_refund and cash_refund types where the refund is applied against prior transactions. Supported by Sage Intacct and Zoho Books."""
    tax_code: NotRequired[Nullable[str]]
    r"""Applicable tax id/code override if tax is not supplied on a line item basis."""
    discount_percentage: NotRequired[Nullable[float]]
    r"""Discount percentage applied to this refund."""
    discount_amount: NotRequired[Nullable[float]]
    r"""Discount amount applied to this refund."""
    note: NotRequired[Nullable[str]]
    r"""Optional note to be associated with the refund."""
    customer_memo: NotRequired[Nullable[str]]
    r"""Customer memo"""
    reference: NotRequired[Nullable[str]]
    r"""Optional reference message for the refund."""
    billing_address: NotRequired[AddressTypedDict]
    shipping_address: NotRequired[AddressTypedDict]
    department: NotRequired[Nullable[LinkedDepartmentTypedDict]]
    location: NotRequired[Nullable[LinkedLocationTypedDict]]
    tracking_categories: NotRequired[
        Nullable[List[Nullable[LinkedTrackingCategoryTypedDict]]]
    ]
    r"""A list of linked tracking categories."""
    custom_mappings: NotRequired[Nullable[Dict[str, Any]]]
    r"""When custom mappings are configured on the resource, the result is included here."""
    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."""
    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."""
    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 Refund(BaseModel):
    id: str
    r"""Unique identifier representing the refund"""

    total_amount: Nullable[float]
    r"""The total amount of the transaction or record"""

    number: OptionalNullable[str] = UNSET
    r"""Reference number for the refund."""

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

    company_id: OptionalNullable[str] = UNSET
    r"""The company ID the transaction belongs to"""

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

    currency_rate: OptionalNullable[float] = UNSET
    r"""Currency Exchange Rate at the time entity was recorded/generated."""

    tax_inclusive: OptionalNullable[bool] = UNSET
    r"""Amounts are including tax"""

    sub_total: OptionalNullable[float] = UNSET
    r"""Subtotal amount, normally before tax."""

    total_tax: OptionalNullable[float] = UNSET
    r"""Total tax amount applied to this transaction."""

    refund_date: OptionalNullable[datetime] = UNSET
    r"""The date of the refund - YYYY-MM-DDThh:mm:ss.sTZD"""

    status: Annotated[
        Optional[RefundStatus], PlainValidator(validate_open_enum(False))
    ] = None
    r"""Status of refund. Maps to: QBO (limited status), NetSuite CashRefund status, Sage Intacct state (draft/posted/voided), Zoho Books vis_state."""

    type: Annotated[Optional[RefundType], PlainValidator(validate_open_enum(False))] = (
        None
    )
    r"""Type of refund. `refund_receipt` for itemized refunds with product/service lines and payment (QBO RefundReceipt, NetSuite CashRefund). `cash_refund` for cash-out refunds with GL distribution or allocations (Sage Intacct). `credit_note_refund` for refunds applied against a credit note (Zoho Books)."""

    payment_method: OptionalNullable[str] = UNSET
    r"""Payment method used for the transaction, such as cash, credit card, bank transfer, or check"""

    payment_method_reference: OptionalNullable[str] = UNSET
    r"""Optional reference message returned by payment method on processing"""

    payment_method_id: OptionalNullable[str] = UNSET
    r"""A unique identifier for an object."""

    account: OptionalNullable[LinkedLedgerAccount] = UNSET

    line_items: Optional[List[InvoiceLineItem]] = None
    r"""Line items for itemized refunds (type: refund_receipt). Used when the refund includes product/service details with quantities and pricing. Supported by QBO RefundReceipt and NetSuite CashRefund."""

    allocations: Optional[List[Allocation]] = None
    r"""Allocations linking refund to existing documents (invoices, credit notes, overpayments). Used for credit_note_refund and cash_refund types where the refund is applied against prior transactions. Supported by Sage Intacct and Zoho Books."""

    tax_code: OptionalNullable[str] = UNSET
    r"""Applicable tax id/code override if tax is not supplied on a line item basis."""

    discount_percentage: OptionalNullable[float] = UNSET
    r"""Discount percentage applied to this refund."""

    discount_amount: OptionalNullable[float] = UNSET
    r"""Discount amount applied to this refund."""

    note: OptionalNullable[str] = UNSET
    r"""Optional note to be associated with the refund."""

    customer_memo: OptionalNullable[str] = UNSET
    r"""Customer memo"""

    reference: OptionalNullable[str] = UNSET
    r"""Optional reference message for the refund."""

    billing_address: Optional[Address] = None

    shipping_address: Optional[Address] = None

    department: OptionalNullable[LinkedDepartment] = UNSET

    location: OptionalNullable[LinkedLocation] = UNSET

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

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

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

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

    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("currency")
    def serialize_currency(self, value):
        if isinstance(value, str):
            try:
                return models.Currency(value)
            except ValueError:
                return value
        return value

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

    @field_serializer("type")
    def serialize_type(self, value):
        if isinstance(value, str):
            try:
                return models.RefundType(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "number",
            "customer",
            "company_id",
            "currency",
            "currency_rate",
            "tax_inclusive",
            "sub_total",
            "total_tax",
            "refund_date",
            "status",
            "type",
            "payment_method",
            "payment_method_reference",
            "payment_method_id",
            "account",
            "line_items",
            "allocations",
            "tax_code",
            "discount_percentage",
            "discount_amount",
            "note",
            "customer_memo",
            "reference",
            "billing_address",
            "shipping_address",
            "department",
            "location",
            "tracking_categories",
            "custom_mappings",
            "custom_fields",
            "row_version",
            "updated_by",
            "created_by",
            "updated_at",
            "created_at",
            "pass_through",
        ]
        nullable_fields = [
            "number",
            "customer",
            "company_id",
            "currency",
            "currency_rate",
            "tax_inclusive",
            "sub_total",
            "total_amount",
            "total_tax",
            "refund_date",
            "payment_method",
            "payment_method_reference",
            "payment_method_id",
            "account",
            "tax_code",
            "discount_percentage",
            "discount_amount",
            "note",
            "customer_memo",
            "reference",
            "department",
            "location",
            "tracking_categories",
            "custom_mappings",
            "row_version",
            "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
