# coding: utf-8

"""
    LUSID API

    FINBOURNE Technology  # noqa: E501

    Contact: info@finbourne.com
    Generated by OpenAPI Generator (https://openapi-generator.tech)

    Do not edit the class manually.
"""


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


from typing import List, Dict, Optional, Any, Union, TYPE_CHECKING
from typing_extensions import Annotated
from pydantic.v1 import BaseModel, StrictStr, StrictInt, StrictBool, StrictFloat, StrictBytes, Field, validator, ValidationError, conlist, constr
from datetime import datetime
from lusid.models.currency_and_amount import CurrencyAndAmount
from lusid.models.otc_confirmation import OtcConfirmation
from lusid.models.perpetual_property import PerpetualProperty
from lusid.models.resource_id import ResourceId
from lusid.models.strategy import Strategy
from lusid.models.transaction_price import TransactionPrice

class TransactionRequest(BaseModel):
    """
    TransactionRequest
    """
    transaction_id:  StrictStr = Field(...,alias="transactionId", description="The unique identifier of the transaction.") 
    type:  StrictStr = Field(...,alias="type", description="The type of the transaction, for example 'Buy' or 'Sell'. The transaction type must have been pre-configured using the System Configuration API. If not, this operation will succeed but you are not able to calculate holdings for the portfolio that include this transaction.") 
    instrument_identifiers: Dict[str, Optional[StrictStr]] = Field(description="A set of instrument identifiers that can resolve the transaction to a unique instrument.", alias="instrumentIdentifiers")
    transaction_date:  StrictStr = Field(...,alias="transactionDate", description="The date of the transaction.") 
    settlement_date:  StrictStr = Field(...,alias="settlementDate", description="The settlement date of the transaction.") 
    units: Union[StrictFloat, StrictInt] = Field(description="The number of units of the transacted instrument.")
    transaction_price: Optional[TransactionPrice] = Field(default=None, alias="transactionPrice")
    total_consideration: CurrencyAndAmount = Field(alias="totalConsideration")
    exchange_rate: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The exchange rate between the transaction and settlement currency (settlement currency being represented by TotalConsideration.Currency). For example, if the transaction currency is USD and the settlement currency is GBP, this would be the appropriate USD/GBP rate.", alias="exchangeRate")
    transaction_currency:  Optional[StrictStr] = Field(None,alias="transactionCurrency", description="The transaction currency.") 
    properties: Optional[Dict[str, PerpetualProperty]] = Field(default=None, description="A list of unique transaction properties and associated values to store for the transaction. Each property must be from the 'Transaction' domain.")
    counterparty_id:  Optional[StrictStr] = Field(None,alias="counterpartyId", description="The identifier for the counterparty of the transaction.") 
    source:  Optional[StrictStr] = Field(None,alias="source", description="The source of the transaction. This is used to look up the appropriate transaction group set in the transaction type configuration.") 
    otc_confirmation: Optional[OtcConfirmation] = Field(default=None, alias="otcConfirmation")
    order_id: Optional[ResourceId] = Field(default=None, alias="orderId")
    allocation_id: Optional[ResourceId] = Field(default=None, alias="allocationId")
    custodian_account_id: Optional[ResourceId] = Field(default=None, alias="custodianAccountId")
    transaction_group_id:  Optional[StrictStr] = Field(None,alias="transactionGroupId", description="The identifier for grouping economic events across multiple transactions") 
    strategy_tag: Optional[List[Strategy]] = Field(default=None, description="A list of strategies representing the allocation of units across multiple sub-holding keys", alias="strategyTag")
    __properties = ["transactionId", "type", "instrumentIdentifiers", "transactionDate", "settlementDate", "units", "transactionPrice", "totalConsideration", "exchangeRate", "transactionCurrency", "properties", "counterpartyId", "source", "otcConfirmation", "orderId", "allocationId", "custodianAccountId", "transactionGroupId", "strategyTag"]

    class Config:
        """Pydantic configuration"""
        allow_population_by_field_name = True
        validate_assignment = True

    def __str__(self):
        """For `print` and `pprint`"""
        return pprint.pformat(self.dict(by_alias=False))

    def __repr__(self):
        """For `print` and `pprint`"""
        return self.to_str()

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

    def to_json(self) -> str:
        """Returns the JSON representation of the model using alias"""
        return json.dumps(self.to_dict())

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

    def to_dict(self):
        """Returns the dictionary representation of the model using alias"""
        _dict = self.dict(by_alias=True,
                          exclude={
                          },
                          exclude_none=True)
        # override the default output from pydantic by calling `to_dict()` of transaction_price
        if self.transaction_price:
            _dict['transactionPrice'] = self.transaction_price.to_dict()
        # override the default output from pydantic by calling `to_dict()` of total_consideration
        if self.total_consideration:
            _dict['totalConsideration'] = self.total_consideration.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each value in properties (dict)
        _field_dict = {}
        if self.properties:
            for _key in self.properties:
                if self.properties[_key]:
                    _field_dict[_key] = self.properties[_key].to_dict()
            _dict['properties'] = _field_dict
        # override the default output from pydantic by calling `to_dict()` of otc_confirmation
        if self.otc_confirmation:
            _dict['otcConfirmation'] = self.otc_confirmation.to_dict()
        # override the default output from pydantic by calling `to_dict()` of order_id
        if self.order_id:
            _dict['orderId'] = self.order_id.to_dict()
        # override the default output from pydantic by calling `to_dict()` of allocation_id
        if self.allocation_id:
            _dict['allocationId'] = self.allocation_id.to_dict()
        # override the default output from pydantic by calling `to_dict()` of custodian_account_id
        if self.custodian_account_id:
            _dict['custodianAccountId'] = self.custodian_account_id.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in strategy_tag (list)
        _items = []
        if self.strategy_tag:
            for _item in self.strategy_tag:
                if _item:
                    _items.append(_item.to_dict())
            _dict['strategyTag'] = _items
        # set to None if exchange_rate (nullable) is None
        # and __fields_set__ contains the field
        if self.exchange_rate is None and "exchange_rate" in self.__fields_set__:
            _dict['exchangeRate'] = None

        # set to None if transaction_currency (nullable) is None
        # and __fields_set__ contains the field
        if self.transaction_currency is None and "transaction_currency" in self.__fields_set__:
            _dict['transactionCurrency'] = None

        # set to None if properties (nullable) is None
        # and __fields_set__ contains the field
        if self.properties is None and "properties" in self.__fields_set__:
            _dict['properties'] = None

        # set to None if counterparty_id (nullable) is None
        # and __fields_set__ contains the field
        if self.counterparty_id is None and "counterparty_id" in self.__fields_set__:
            _dict['counterpartyId'] = None

        # set to None if source (nullable) is None
        # and __fields_set__ contains the field
        if self.source is None and "source" in self.__fields_set__:
            _dict['source'] = None

        # set to None if transaction_group_id (nullable) is None
        # and __fields_set__ contains the field
        if self.transaction_group_id is None and "transaction_group_id" in self.__fields_set__:
            _dict['transactionGroupId'] = None

        # set to None if strategy_tag (nullable) is None
        # and __fields_set__ contains the field
        if self.strategy_tag is None and "strategy_tag" in self.__fields_set__:
            _dict['strategyTag'] = None

        return _dict

    @classmethod
    def from_dict(cls, obj: dict) -> TransactionRequest:
        """Create an instance of TransactionRequest from a dict"""
        if obj is None:
            return None

        if not isinstance(obj, dict):
            return TransactionRequest.parse_obj(obj)

        _obj = TransactionRequest.parse_obj({
            "transaction_id": obj.get("transactionId"),
            "type": obj.get("type"),
            "instrument_identifiers": obj.get("instrumentIdentifiers"),
            "transaction_date": obj.get("transactionDate"),
            "settlement_date": obj.get("settlementDate"),
            "units": obj.get("units"),
            "transaction_price": TransactionPrice.from_dict(obj.get("transactionPrice")) if obj.get("transactionPrice") is not None else None,
            "total_consideration": CurrencyAndAmount.from_dict(obj.get("totalConsideration")) if obj.get("totalConsideration") is not None else None,
            "exchange_rate": obj.get("exchangeRate"),
            "transaction_currency": obj.get("transactionCurrency"),
            "properties": dict(
                (_k, PerpetualProperty.from_dict(_v))
                for _k, _v in obj.get("properties").items()
            )
            if obj.get("properties") is not None
            else None,
            "counterparty_id": obj.get("counterpartyId"),
            "source": obj.get("source"),
            "otc_confirmation": OtcConfirmation.from_dict(obj.get("otcConfirmation")) if obj.get("otcConfirmation") is not None else None,
            "order_id": ResourceId.from_dict(obj.get("orderId")) if obj.get("orderId") is not None else None,
            "allocation_id": ResourceId.from_dict(obj.get("allocationId")) if obj.get("allocationId") is not None else None,
            "custodian_account_id": ResourceId.from_dict(obj.get("custodianAccountId")) if obj.get("custodianAccountId") is not None else None,
            "transaction_group_id": obj.get("transactionGroupId"),
            "strategy_tag": [Strategy.from_dict(_item) for _item in obj.get("strategyTag")] if obj.get("strategyTag") is not None else None
        })
        return _obj

TransactionRequest.update_forward_refs()
