# coding: utf-8

"""
    Cloudbeds Accounting Service API

    The Cloudbeds Accounting Service API provides programmatic access to financial data and operations for hospitality properties. Use this API to manage transactions, folios, deposits, accounts receivable ledgers, trial balances, and related accounting configuration.  **Key concepts:** - **Transactions** represent individual financial entries (charges, payments,   taxes, fees) associated with a source such as a reservation, group profile,   or house account.  - **Folios** organize transactions into logical groups within a source. You   can create custom folios and move or route transactions between them.  - **Source Balances** provide a real-time financial summary (charges, payments,   balance due, tax/fee breakdowns) for a reservation, group profile, house   account, or accounts receivable ledger.  - **Accounts Receivable (AR) Ledgers** track outstanding balances that have   been transferred from reservations or group profiles for later collection.  - **Trial Balance** is a daily financial reconciliation report that summarizes   ledger activity across guest, deposit, and AR ledgers.  - **Custom Codes** let you map Cloudbeds internal transaction codes to your   own chart-of-accounts codes and general ledger codes.   **Authentication:** All endpoints require a valid OAuth2 bearer token. Endpoints are protected by scopes: `read:payment` for read operations and `write:payment` for mutating operations. A few search endpoints use POST with a request body to support complex filter criteria; these require the `read:payment` scope.  **Base URL:** Use `https://api.cloudbeds.com` for production and `https://api.cloudbeds-stage.com` for staging. All endpoint paths are prefixed with `/accounting/v1.0`.  **Property context:** Every request must include the `X-Property-ID` header to identify which property the request applies to.  **Monetary amounts:** Unless otherwise noted, monetary amounts are expressed in the smallest currency unit (e.g., cents for USD). Use the `currencyScale` field to determine the number of decimal places.  **Pagination:** Paginated endpoints return a `nextPageToken` value. Pass this token in subsequent requests to retrieve the next page of results. When `nextPageToken` is null or absent, you have reached the last page. 

    The version of the OpenAPI document: v0
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""  # noqa: E501


from __future__ import annotations
import pprint
import re  # noqa: F401
import json

from datetime import date, datetime
from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional, Union
from cloudbeds_accounting.models.account import Account
from cloudbeds_accounting.models.source_kind import SourceKind
from typing import Optional, Set
from typing_extensions import Self

class TransactionResponse(BaseModel):
    """
    TransactionResponse
    """ # noqa: E501
    id: Optional[StrictStr] = Field(default=None, description="Id of the transaction.")
    property_id: Optional[StrictStr] = Field(default=None, description="Property ID where the transaction was created.", alias="propertyId")
    internal_transaction_code: Optional[StrictStr] = Field(default=None, description="Internal code for the transaction, managed by Cloudbeds.", alias="internalTransactionCode")
    custom_transaction_code: Optional[StrictStr] = Field(default=None, description="Custom code for the transaction, managed by Property.", alias="customTransactionCode")
    general_ledger_custom_code: Optional[StrictStr] = Field(default=None, description="Custom code for general ledger, managed by Property.", alias="generalLedgerCustomCode")
    amount: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Amount of the transaction.")
    currency_scale: Optional[StrictInt] = Field(default=None, description="Number of decimal places for the currency.", alias="currencyScale")
    currency: Optional[StrictStr] = Field(default=None, description="Currency (ISO code) applied to the amount of the transaction.")
    customer_id: Optional[StrictStr] = Field(default=None, description="Id of the user who perform the transaction, also know as guest id.", alias="customerId")
    root_id: Optional[StrictStr] = Field(default=None, description="Root Id of the transaction, it contains the id of the transaction that is related to it.", alias="rootId")
    parent_id: Optional[StrictStr] = Field(default=None, description="Id of the transaction that is parent of this one. For example Tax on top of a rate, tax on top of a fee, etc.", alias="parentId")
    source_id: Optional[StrictStr] = Field(default=None, description="Id of the source. It is related with the source_kind, so if sourceKind is RESERVATION, is the reservation id.", alias="sourceId")
    sub_source_id: Optional[StrictStr] = Field(default=None, description="Id of the sub source. At the moment only for reservations that is the booking_room_id.", alias="subSourceId")
    source_kind: Optional[SourceKind] = Field(default=None, alias="sourceKind")
    account: Optional[Account] = None
    external_relation_id: Optional[StrictStr] = Field(default=None, description="External relation id, for example if the transaction is a payment it will contain payment id.", alias="externalRelationId")
    external_relation_kind: Optional[StrictStr] = Field(default=None, description="Kind of the external relation id, for example if transaction is a payment it will contain PAYMENT.", alias="externalRelationKind")
    origin_id: Optional[StrictStr] = Field(default=None, description="Id of origin of the transaction. For example if the transaction is created based on a rate, is the rate id.", alias="originId")
    routed_from: Optional[StrictStr] = Field(default=None, description="Id of the transaction that was routed from. It can be null.", alias="routedFrom")
    quantity: Optional[StrictInt] = Field(default=None, description="Amount of items purchased.")
    description: Optional[StrictStr] = Field(default=None, description="Description of the transaction.")
    user_id: Optional[StrictStr] = Field(default=None, description="ID of the user who created the transaction", alias="userId")
    source_datetime: Optional[datetime] = Field(default=None, description="Date time the source was created. (ISO 8601) in UTC", alias="sourceDatetime")
    transaction_datetime: Optional[datetime] = Field(default=None, description="Date time when the transaction should be created at. (ISO 8601) in UTC", alias="transactionDatetime")
    transaction_datetime_property_time: Optional[datetime] = Field(default=None, description="Date time when the transaction should be created at base on the property timezone.", alias="transactionDatetimePropertyTime")
    service_date: Optional[date] = Field(default=None, description="Date when the posted transaction was created (property time).", alias="serviceDate")
    created_at: Optional[datetime] = Field(default=None, description="Date time when the transaction was inserted on the database. (ISO 8601) in UTC", alias="createdAt")
    source_identifier: Optional[StrictStr] = Field(default=None, description="If source_kind = RESERVATION, this field will contain a reservation identifier. For a transaction with source_kind = GROUP_PROFILE, this field will contain a group code. For source_king = HOUSE_ACCOUNT it will be null.", alias="sourceIdentifier")
    sub_source_identifier: Optional[StrictStr] = Field(default=None, description="identifier of a booking room", alias="subSourceIdentifier")
    notes: Optional[StrictStr] = Field(default=None, description="Notes associated with the transaction")
    __properties: ClassVar[List[str]] = ["id", "propertyId", "internalTransactionCode", "customTransactionCode", "generalLedgerCustomCode", "amount", "currencyScale", "currency", "customerId", "rootId", "parentId", "sourceId", "subSourceId", "sourceKind", "account", "externalRelationId", "externalRelationKind", "originId", "routedFrom", "quantity", "description", "userId", "sourceDatetime", "transactionDatetime", "transactionDatetimePropertyTime", "serviceDate", "createdAt", "sourceIdentifier", "subSourceIdentifier", "notes"]

    @field_validator('external_relation_kind')
    def external_relation_kind_validate_enum(cls, value):
        """Validates the enum, returning unknown_default_open_api for unrecognized values"""
        if value is None:
            return value

        _allowed_values = set(['ROOM', 'PAYMENT', 'ITEM', 'ITEM_POS', 'ADDON', 'RESERVATION', 'ACCOUNTS_RECEIVABLE', 'ROOM_REVENUE', 'TAX', 'FEE', 'ADJUSTMENT', 'PAYMENT_FEE', 'BOOKABLE_RESOURCE', 'unknown_default_open_api'])
        if value not in _allowed_values:
            return 'unknown_default_open_api'
        return value

    model_config = ConfigDict(
        populate_by_name=True,
        validate_assignment=True,
        protected_namespaces=(),
    )


    def to_str(self) -> str:
        """Returns the string representation of the model using alias"""
        return pprint.pformat(self.model_dump(by_alias=True))

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
        return json.dumps(self.to_dict())

    @classmethod
    def from_json(cls, json_str: str) -> Optional[Self]:
        """Create an instance of TransactionResponse from a JSON string"""
        return cls.from_dict(json.loads(json_str))

    def to_dict(self) -> Dict[str, Any]:
        """Return the dictionary representation of the model using alias.

        This has the following differences from calling pydantic's
        `self.model_dump(by_alias=True)`:

        * `None` is only added to the output dict for nullable fields that
          were set at model initialization. Other fields with value `None`
          are ignored.
        """
        excluded_fields: Set[str] = set([
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of account
        if self.account:
            _dict['account'] = self.account.to_dict()
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of TransactionResponse from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return cls.model_validate(obj)

        _obj = cls.model_validate({
            "id": obj.get("id"),
            "propertyId": obj.get("propertyId"),
            "internalTransactionCode": obj.get("internalTransactionCode"),
            "customTransactionCode": obj.get("customTransactionCode"),
            "generalLedgerCustomCode": obj.get("generalLedgerCustomCode"),
            "amount": obj.get("amount"),
            "currencyScale": obj.get("currencyScale"),
            "currency": obj.get("currency"),
            "customerId": obj.get("customerId"),
            "rootId": obj.get("rootId"),
            "parentId": obj.get("parentId"),
            "sourceId": obj.get("sourceId"),
            "subSourceId": obj.get("subSourceId"),
            "sourceKind": obj.get("sourceKind"),
            "account": Account.from_dict(obj["account"]) if obj.get("account") is not None else None,
            "externalRelationId": obj.get("externalRelationId"),
            "externalRelationKind": obj.get("externalRelationKind"),
            "originId": obj.get("originId"),
            "routedFrom": obj.get("routedFrom"),
            "quantity": obj.get("quantity"),
            "description": obj.get("description"),
            "userId": obj.get("userId"),
            "sourceDatetime": obj.get("sourceDatetime"),
            "transactionDatetime": obj.get("transactionDatetime"),
            "transactionDatetimePropertyTime": obj.get("transactionDatetimePropertyTime"),
            "serviceDate": obj.get("serviceDate"),
            "createdAt": obj.get("createdAt"),
            "sourceIdentifier": obj.get("sourceIdentifier"),
            "subSourceIdentifier": obj.get("subSourceIdentifier"),
            "notes": obj.get("notes")
        })
        return _obj


