# coding: utf-8

"""
    Zuora API Reference

    REST API reference for the Zuora Billing, Payments, and Central Platform! Check out the [REST API Overview](https://www.zuora.com/developer/api-references/api/overview/).

    The version of the OpenAPI document: 2024-05-20
    Contact: docs@zuora.com
    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
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from zuora_sdk.models.get_journal_entry_item_response import GetJournalEntryItemResponse
from zuora_sdk.models.get_journal_entry_segment_response import GetJournalEntrySegmentResponse
from zuora_sdk.models.journal_entry_status import JournalEntryStatus
from zuora_sdk.models.transferred_to_accounting_status import TransferredToAccountingStatus
from typing import Optional, Set
from typing_extensions import Self

class GetJournalEntryDetailResponse(BaseModel):
    """
    GetJournalEntryDetailResponse
    """ # noqa: E501
    # avoid validation
    def __init__(self, **kwargs):
        # Directly assign values without validation using `construct()`
        model = self.construct(**kwargs)
        self.__dict__.update(model.__dict__)

        _dict_all = convert_snake_dict_to_camel(kwargs, self.model_fields, self.__properties)

        _dict = self.to_alias_dict(_dict_all)
        for field_name, field_info in self.model_fields.items():
            alias = field_info.alias or field_name
            if alias in _dict:
                self.__dict__[field_name] = _dict.get(alias)
        self.update_additional_properties(self, _dict_all)
        pass

    def __setattr__(self, name, value):
        # Override setattr to bypass validation when setting attributes
        object.__setattr__(self, name, value)

    accounting_period_name: Optional[StrictStr] = Field(default=None, description="Name of the accounting period that the journal entry belongs to. ", alias="accountingPeriodName")
    aggregate_currency: Optional[StrictBool] = Field(default=None, description="Returns true if the journal entry is aggregating currencies. That is, if the journal entry was created when the `Aggregate transactions with different currencies during a Journal Run` setting was configured to `Yes`. Otherwise, returns `false`. ", alias="aggregateCurrency")
    currency: Optional[StrictStr] = Field(default=None, description="Currency used. ")
    home_currency: Optional[StrictStr] = Field(default=None, description="Home currency used. ", alias="homeCurrency")
    journal_entry_date: Optional[date] = Field(default=None, description="Date of the journal entry. ", alias="journalEntryDate")
    journal_entry_items: Optional[List[GetJournalEntryItemResponse]] = Field(default=None, description="Key name that represents the list of journal entry items. ", alias="journalEntryItems")
    notes: Optional[StrictStr] = Field(default=None, description=" Additional information about this record. Character limit: 2,000 ")
    number: Optional[StrictStr] = Field(default=None, description="Journal entry number in the format JE-00000001. ")
    organization_label: Optional[StrictStr] = Field(default=None, description="Organization label. ", alias="organizationLabel")
    segments: Optional[List[GetJournalEntrySegmentResponse]] = Field(default=None, description="List of segments that apply to the summary journal entry. ")
    status: Optional[JournalEntryStatus] = None
    success: Optional[StrictBool] = Field(default=None, description="Returns `true` if the request was processed successfully. ")
    time_period_end: Optional[date] = Field(default=None, description="End date of time period included in the journal entry. ", alias="timePeriodEnd")
    time_period_start: Optional[date] = Field(default=None, description="Start date of time period included in the journal entry. ", alias="timePeriodStart")
    transaction_type: Optional[StrictStr] = Field(default=None, description="Transaction type of the transactions included in the summary journal entry. ", alias="transactionType")
    transfer_date_time: Optional[StrictStr] = Field(default=None, description="Date and time that transferredToAccounting was changed to `Yes`. This field is returned only when transferredToAccounting is `Yes`. Otherwise, this field is `null`. ", alias="transferDateTime")
    transferred_by: Optional[StrictStr] = Field(default=None, description="User ID of the person who changed transferredToAccounting to `Yes`. This field is returned only when transferredToAccounting is `Yes`. Otherwise, this field is `null`. ", alias="transferredBy")
    transferred_to_accounting: Optional[TransferredToAccountingStatus] = Field(default=None, alias="transferredToAccounting")
    additional_properties: Dict[str, Any] = {}
    __properties: ClassVar[List[str]] = ["accountingPeriodName", "aggregateCurrency", "currency", "homeCurrency", "journalEntryDate", "journalEntryItems", "notes", "number", "organizationLabel", "segments", "status", "success", "timePeriodEnd", "timePeriodStart", "transactionType", "transferDateTime", "transferredBy", "transferredToAccounting"]

    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 GetJournalEntryDetailResponse 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.
        * Fields in `self.additional_properties` are added to the output dict.
        """
        excluded_fields: Set[str] = set([
            "additional_properties",
        ])

        _dict = self.model_dump(
            by_alias=True,
            exclude=excluded_fields,
            exclude_none=True,
        )
        # override the default output from pydantic by calling `to_dict()` of each item in journal_entry_items (list)
        _items = []
        if self.journal_entry_items:
            for _item_journal_entry_items in self.journal_entry_items:
                if _item_journal_entry_items:
                    _items.append(_item_journal_entry_items.to_dict())
            _dict['journalEntryItems'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in segments (list)
        _items = []
        if self.segments:
            for _item_segments in self.segments:
                if _item_segments:
                    _items.append(_item_segments.to_dict())
            _dict['segments'] = _items
        # puts key-value pairs in additional_properties in the top level
        if self.additional_properties is not None:
            for _key, _value in self.additional_properties.items():
                _dict[_key] = _value

        return _dict

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

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

        obj = convert_snake_dict_to_camel(obj, cls.model_fields, cls.__properties)

        _obj = cls.model_validate(cls.to_alias_dict(obj))
        return cls.update_additional_properties(_obj, obj)

    @classmethod
    def update_additional_properties(cls, obj, _dict: Optional[Dict[str, Any]]):
        # store additional fields in additional_properties

        # store additional fields in additional_properties
        for _key in _dict.keys():
            if _key not in cls.__properties:
                obj.additional_properties[_key] = _dict.get(_key)


        return obj
        pass

    @classmethod
    def to_alias_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:

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

        return {
            "accountingPeriodName": obj.get("accountingPeriodName"),
            "aggregateCurrency": obj.get("aggregateCurrency"),
            "currency": obj.get("currency"),
            "homeCurrency": obj.get("homeCurrency"),
            "journalEntryDate": obj.get("journalEntryDate"),
            "journalEntryItems": [GetJournalEntryItemResponse.from_dict(_item) for _item in obj["journalEntryItems"]] if obj.get("journalEntryItems") is not None else None,
            "notes": obj.get("notes"),
            "number": obj.get("number"),
            "organizationLabel": obj.get("organizationLabel"),
            "segments": [GetJournalEntrySegmentResponse.from_dict(_item) for _item in obj["segments"]] if obj.get("segments") is not None else None,
            "status": obj.get("status"),
            "success": obj.get("success"),
            "timePeriodEnd": obj.get("timePeriodEnd"),
            "timePeriodStart": obj.get("timePeriodStart"),
            "transactionType": obj.get("transactionType"),
            "transferDateTime": obj.get("transferDateTime"),
            "transferredBy": obj.get("transferredBy"),
            "transferredToAccounting": obj.get("transferredToAccounting")
        }
        return _obj


def convert_snake_dict_to_camel(_dict: dict, model_fields, properties):
    if not isinstance(_dict, dict):
        return _dict
    new_dict = {}
    for k, v in _dict.items():
        if k in model_fields:
            # model_fields: key is attribute name like bill_to_contact,
            alias = model_fields.get(k).alias or k
            new_dict[alias] = v
            pass
        else:
            new_key = snake_to_camel(k)
            if properties is not None and isinstance(properties, list) and new_key in properties:
                new_dict[new_key] = v
            else:
                new_dict[k] = v
    return new_dict
    pass


def snake_to_camel(name):
    if name is None or '_' not in name:
        return name
    components = name.split('_')
    return components[0] + ''.join(x.title() for x in components[1:])
