# 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, StrictFloat, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing_extensions import Annotated
from zuora_sdk.models.get_fulfillment import GetFulfillment
from zuora_sdk.models.order_line_item_billing_rule import OrderLineItemBillingRule
from zuora_sdk.models.order_line_item_category import OrderLineItemCategory
from zuora_sdk.models.order_line_item_inline_discount_type import OrderLineItemInlineDiscountType
from zuora_sdk.models.order_line_item_state import OrderLineItemState
from zuora_sdk.models.order_line_item_type import OrderLineItemType
from zuora_sdk.models.tax_mode import TaxMode
from typing import Optional, Set
from typing_extensions import Self

class GetOrderLineItem(BaseModel):
    """
    GetOrderLineItem
    """ # 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)

    id: Optional[StrictStr] = Field(default=None, description="The sytem generated Id for the Order Line Item. ")
    amended_by_order_on: Optional[StrictStr] = Field(default=None, description="The date when the rate plan charge is amended through an order or amendment. This field is to standardize the booking date information to increase audit ability and traceability of data between Zuora Billing and Zuora Revenue. It is mapped as the booking date for a sale order line in Zuora Revenue. ", alias="amendedByOrderOn")
    currency: Optional[StrictStr] = Field(default=None, description="The currency for the Order Line Item. ")
    payment_term: Optional[StrictStr] = Field(default=None, description="The payment term for the Order Line Item ", alias="paymentTerm")
    invoice_template_id: Optional[StrictStr] = Field(default=None, description="The invoice template id for the Order Line Item ", alias="invoiceTemplateId")
    amount: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The calculated gross amount for the Order Line Item. ")
    amount_without_tax: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The calculated gross amount for an order line item excluding tax. If the tax mode is tax exclusive, the value of this field equals that of the `amount` field.  If the tax mode of an order line item is not set, the system treats it as tax exclusive by default. The value of the `amountWithoutTax` field equals that of the `amount` field.  If you create an order line item from the product catalog, the tax mode and tax code of the product rate plan charge are used for the order line item by default. You can still overwrite this default set-up by setting the tax mode and tax code of the order line item. ", alias="amountWithoutTax")
    item_number: Optional[StrictStr] = Field(default=None, description="The number for the Order Line Item. ", alias="itemNumber")
    uom: Optional[StrictStr] = Field(default=None, description="Specifies the units to measure usage.    ", alias="UOM")
    amount_per_unit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The actual charged amount per unit for the Order Line Item.    ", alias="amountPerUnit")
    bill_target_date: Optional[date] = Field(default=None, description="The target date for the Order Line Item to be picked up by bill run for billing.    ", alias="billTargetDate")
    bill_to: Optional[StrictStr] = Field(default=None, description="The ID of a contact that belongs to the billing account of the order line item. Use this field to assign an existing account as the bill-to contact of an order line item.    ", alias="billTo")
    bill_to_snapshot_id: Optional[StrictStr] = Field(default=None, description="The snapshot of the ID for an account used as the sold-to contact of an order line item. This field is used to store the original information about the account, in case the information about the account is changed after the creation of the order line item. The `billToSnapshotId` field is exposed while retrieving the order line item details.    ", alias="billToSnapshotId")
    billing_rule: Optional[OrderLineItemBillingRule] = Field(default=OrderLineItemBillingRule.TRIGGERWITHOUTFULFILLMENT, alias="billingRule")
    accounting_code: Optional[StrictStr] = Field(default=None, description="The accounting code for the Order Line Item.    ", alias="accountingCode")
    adjustment_liability_accounting_code: Optional[StrictStr] = Field(default=None, description="The accounting code on the Order Line Item object for customers using [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration).    ", alias="adjustmentLiabilityAccountingCode")
    adjustment_revenue_accounting_code: Optional[StrictStr] = Field(default=None, description="The accounting code on the Order Line Item object for customers using [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration).    ", alias="adjustmentRevenueAccountingCode")
    contract_asset_accounting_code: Optional[StrictStr] = Field(default=None, description="The accounting code on the Order Line Item object for customers using [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration).    ", alias="contractAssetAccountingCode")
    contract_liability_accounting_code: Optional[StrictStr] = Field(default=None, description="The accounting code on the Order Line Item object for customers using [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration).    ", alias="contractLiabilityAccountingCode")
    contract_recognized_revenue_accounting_code: Optional[StrictStr] = Field(default=None, description="The accounting code on the Order Line Item object for customers using [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration).    ", alias="contractRecognizedRevenueAccountingCode")
    deferred_revenue_accounting_code: Optional[StrictStr] = Field(default=None, description="The deferred revenue accounting code for the Order Line Item.    ", alias="deferredRevenueAccountingCode")
    custom_fields: Optional[Dict[str, Dict[str, Any]]] = Field(default=None, description="Container for custom fields of an Order Line Item object.    ", alias="customFields")
    description: Optional[StrictStr] = Field(default=None, description="The description of the Order Line Item.    ")
    discount: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="This field shows the total discount amount that is applied to an order line item after the `inlineDiscountType`, `inlineDiscountPerUnit` and `quantity` fields are set.     The inline discount is applied to the list price of an order line item (see the `listPrice` field).    ")
    exclude_item_billing_from_revenue_accounting: Optional[StrictBool] = Field(default=None, description="The flag to exclude Order Line Item related invoice items, invoice item adjustments, credit memo items, and debit memo items from revenue accounting.  **Note**: This field is only available if you have the [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration) feature enabled.  ", alias="excludeItemBillingFromRevenueAccounting")
    exclude_item_booking_from_revenue_accounting: Optional[StrictBool] = Field(default=None, description="The flag to exclude Order Line Item from revenue accounting.  **Note**: This field is only available if you have the [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration) feature enabled.  ", alias="excludeItemBookingFromRevenueAccounting")
    revenue_recognition_timing: Optional[StrictStr] = Field(default=None, description="This field is used to dictate the type of revenue recognition timing.", alias="revenueRecognitionTiming")
    revenue_amortization_method: Optional[StrictStr] = Field(default=None, description="This field is used to dictate the type of revenue amortization method.", alias="revenueAmortizationMethod")
    inline_discount_per_unit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="This field is used in accordance with the `inlineDiscountType` field, in the following manner:    * If the `inlineDiscountType` field is set as `Percentage`, this field specifies the discount percentage for each unit of the order line item. For exmaple, if you specify `5` in this field, the discount percentage is 5%.    * If the `inlineDiscountType` field is set as `FixedAmount`, this field specifies the discount amount on each unit of the order line item. For exmaple, if you specify `10` in this field, the discount amount on each unit of the order line item is 10.     Once you set the `inlineDiscountType`, `inlineDiscountPerUnit`, and `listPricePerUnit` fields, the system will automatically generate the `amountPerUnit` field. You shall not set the `amountPerUnit` field by yourself.    ", alias="inlineDiscountPerUnit")
    inline_discount_type: Optional[StrictStr] = Field(default=None, alias="inlineDiscountType")
    invoice_group_number: Optional[Annotated[str, Field(strict=True, max_length=255)]] = Field(default=None, description="The invoice group number associated with the order line item. ", alias="invoiceGroupNumber")
    invoice_owner_account_id: Optional[StrictStr] = Field(default=None, description="The account ID of the invoice owner of the order line item.    ", alias="invoiceOwnerAccountId")
    invoice_owner_account_name: Optional[StrictStr] = Field(default=None, description="The account name of the invoice owner of the order line item.    ", alias="invoiceOwnerAccountName")
    invoice_owner_account_number: Optional[StrictStr] = Field(default=None, description="The account number of the invoice owner of the order line item.    ", alias="invoiceOwnerAccountNumber")
    is_allocation_eligible: Optional[StrictBool] = Field(default=None, description="This field is used to identify if the charge segment is allocation eligible in revenue recognition.     **Note**: This feature is in the **Early Adopter** phase. If you want to use the feature, submit a request at <a href=\"https://support.zuora.com/\" target=\"_blank\">Zuora Global Support</a>, and we will evaluate whether the feature is suitable for your use cases.    ", alias="isAllocationEligible")
    is_unbilled: Optional[StrictBool] = Field(default=None, description="This field is used to dictate how to perform the accounting during revenue recognition.     **Note**: This feature is in the **Early Adopter** phase. If you want to use the feature, submit a request at <a href=\"https://support.zuora.com/\" target=\"_blank\">Zuora Global Support</a>, and we will evaluate whether the feature is suitable for your use cases.    ", alias="isUnbilled")
    item_category: Optional[OrderLineItemCategory] = Field(default=OrderLineItemCategory.SALES, alias="itemCategory")
    item_name: Optional[StrictStr] = Field(default=None, description="The name of the Order Line Item.    ", alias="itemName")
    item_state: Optional[OrderLineItemState] = Field(default=None, alias="itemState")
    item_type: Optional[OrderLineItemType] = Field(default=None, alias="itemType")
    list_price: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The extended list price for an order line item, calculated by the formula: listPrice = listPricePerUnit * quantity    ", alias="listPrice")
    list_price_per_unit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The list price per unit for the Order Line Item.    ", alias="listPricePerUnit")
    original_order_id: Optional[StrictStr] = Field(default=None, description="The ID of the original sale order for a return order line item.  ", alias="originalOrderId")
    original_order_date: Optional[date] = Field(default=None, description="The date when the rate plan charge is created through an order or amendment. This field is to standardize the booking date information to increase audit ability and traceability of data between Zuora Billing and Zuora Revenue. It is mapped as the booking date for a sale order line in Zuora Revenue. ", alias="originalOrderDate")
    original_order_line_item_id: Optional[StrictStr] = Field(default=None, description="The ID of the original sale order line item for a return order line item.  ", alias="originalOrderLineItemId")
    original_order_line_item_number: Optional[StrictStr] = Field(default=None, description="The number of the original sale order line item for a return order line item.  ", alias="originalOrderLineItemNumber")
    original_order_number: Optional[StrictStr] = Field(default=None, description="The number of the original sale order for a return order line item.  ", alias="originalOrderNumber")
    owner_account_id: Optional[StrictStr] = Field(default=None, description="The account ID of the owner of the order line item.    ", alias="ownerAccountId")
    owner_account_name: Optional[StrictStr] = Field(default=None, description="The account name of the owner of the order line item.    ", alias="ownerAccountName")
    owner_account_number: Optional[StrictStr] = Field(default=None, description="The account number of the owner of the order line item.    ", alias="ownerAccountNumber")
    product_code: Optional[StrictStr] = Field(default=None, description="The product code for the Order Line Item.    ", alias="productCode")
    product_rate_plan_charge_id: Optional[StrictStr] = Field(default=None, description="Id of a Product Rate Plan Charge. Only one-time charges are supported.    ", alias="productRatePlanChargeId")
    purchase_order_number: Optional[StrictStr] = Field(default=None, description="Used by customers to specify the Purchase Order Number provided by the buyer.    ", alias="purchaseOrderNumber")
    quantity: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The quantity of units, such as the number of authors in a hosted wiki service.    ")
    quantity_available_for_return: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The quantity that can be returned for an order line item.  ", alias="quantityAvailableForReturn")
    quantity_fulfilled: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The quantity that has been fulfilled by fulfillments for the order line item. This field will be updated automatically when related fulfillments become 'SentToBilling' or 'Complete' state. ", alias="quantityFulfilled")
    quantity_pending_fulfillment: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="The quantity that's need to be fulfilled by fulfillments for the order line item. This field will be updated automatically when related fulfillments become 'SentToBilling' or 'Complete' state. ", alias="quantityPendingFulfillment")
    recognized_revenue_accounting_code: Optional[StrictStr] = Field(default=None, description="The recognized revenue accounting code for the Order Line Item.    ", alias="recognizedRevenueAccountingCode")
    related_subscription_number: Optional[StrictStr] = Field(default=None, description="Use this field to relate an order line item to a subscription when you create the order line item.     * To relate an order line item to a new subscription which is yet to create in the same \"Create an order\" call, use this field in combination with the `subscriptions` > `subscriptionNumber` field in the \"Create order\" operation. Specify this field to the same value as that of the 'subscriptions' > `subscriptionNumber` field when you make the \"Create order\" call.    * To relate an order line item to an existing subscription, specify this field to the subscription number of the existing subscription.    ", alias="relatedSubscriptionNumber")
    requires_fulfillment: Optional[StrictBool] = Field(default=None, description="The flag to show whether fulfillment is needed or not. It's derived from billing rule of the Order Line Item.    ", alias="requiresFulfillment")
    revenue_recognition_rule: Optional[StrictStr] = Field(default=None, description="The Revenue Recognition rule for the Order Line Item.    ", alias="revenueRecognitionRule")
    sequence_set_id: Optional[StrictStr] = Field(default=None, description="The ID of the sequence set associated with the OrderLineItem.    ", alias="sequenceSetId")
    sold_to: Optional[StrictStr] = Field(default=None, description="The ID of a contact that belongs to the owner acount or billing account of the order line item. Use this field to assign an existing account as the sold-to contact of an order line item.    ", alias="soldTo")
    sold_to_snapshot_id: Optional[StrictStr] = Field(default=None, description="The snapshot of the ID for an account used as the sold-to contact of an order line item. This field is used to store the original information about the account, in case the information about the account is changed after the creation of the order line item. The `soldToSnapshotId` field is exposed while retrieving the order line item details.    ", alias="soldToSnapshotId")
    ship_to: Optional[StrictStr] = Field(default=None, description="The ID of a contact that belongs to the owner account or billing account of the order line item. Use this field to assign an existing account as the ship-to contact of an order line item.    ", alias="shipTo")
    ship_to_snapshot_id: Optional[StrictStr] = Field(default=None, description="The snapshot of the ID for an account used as the ship-to contact of an order line item. This field is used to store the original information about the account, in case the information about the account is changed after the creation of the order line item. The `shipToSnapshotId` field is exposed while retrieving the order line item details.    ", alias="shipToSnapshotId")
    tax_code: Optional[StrictStr] = Field(default=None, description="The tax code for the Order Line Item.    ", alias="taxCode")
    tax_mode: Optional[TaxMode] = Field(default=None, alias="taxMode")
    transaction_end_date: Optional[date] = Field(default=None, description="The date a transaction is completed. The default value of this field is the transaction start date. Also, the value of this field should always equal or be later than the value of the `transactionStartDate` field.    ", alias="transactionEndDate")
    transaction_start_date: Optional[date] = Field(default=None, description="The date a transaction starts. The default value of this field is the order date.    ", alias="transactionStartDate")
    unbilled_receivables_accounting_code: Optional[StrictStr] = Field(default=None, description="The accounting code on the Order Line Item object for customers using [Zuora Billing - Revenue Integration](https://knowledgecenter.zuora.com/Zuora_Revenue/Zuora_Billing_-_Revenue_Integration).    ", alias="unbilledReceivablesAccountingCode")
    fulfillments: Optional[List[GetFulfillment]] = Field(default=None, description="Container for the fulfillments attached to an order line item. ")
    additional_properties: Dict[str, Any] = {}
    __properties: ClassVar[List[str]] = ["id", "amendedByOrderOn", "currency", "paymentTerm", "invoiceTemplateId", "amount", "amountWithoutTax", "itemNumber", "UOM", "amountPerUnit", "billTargetDate", "billTo", "billToSnapshotId", "billingRule", "accountingCode", "adjustmentLiabilityAccountingCode", "adjustmentRevenueAccountingCode", "contractAssetAccountingCode", "contractLiabilityAccountingCode", "contractRecognizedRevenueAccountingCode", "deferredRevenueAccountingCode", "customFields", "description", "discount", "excludeItemBillingFromRevenueAccounting", "excludeItemBookingFromRevenueAccounting", "revenueRecognitionTiming", "revenueAmortizationMethod", "inlineDiscountPerUnit", "inlineDiscountType", "invoiceGroupNumber", "invoiceOwnerAccountId", "invoiceOwnerAccountName", "invoiceOwnerAccountNumber", "isAllocationEligible", "isUnbilled", "itemCategory", "itemName", "itemState", "itemType", "listPrice", "listPricePerUnit", "originalOrderId", "originalOrderDate", "originalOrderLineItemId", "originalOrderLineItemNumber", "originalOrderNumber", "ownerAccountId", "ownerAccountName", "ownerAccountNumber", "productCode", "productRatePlanChargeId", "purchaseOrderNumber", "quantity", "quantityAvailableForReturn", "quantityFulfilled", "quantityPendingFulfillment", "recognizedRevenueAccountingCode", "relatedSubscriptionNumber", "requiresFulfillment", "revenueRecognitionRule", "sequenceSetId", "soldTo", "soldToSnapshotId", "shipTo", "shipToSnapshotId", "taxCode", "taxMode", "transactionEndDate", "transactionStartDate", "unbilledReceivablesAccountingCode", "fulfillments"]

    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 GetOrderLineItem 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 fulfillments (list)
        _items = []
        if self.fulfillments:
            for _item_fulfillments in self.fulfillments:
                if _item_fulfillments:
                    _items.append(_item_fulfillments.to_dict())
            _dict['fulfillments'] = _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 GetOrderLineItem 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 {
            "id": obj.get("id"),
            "amendedByOrderOn": obj.get("amendedByOrderOn"),
            "currency": obj.get("currency"),
            "paymentTerm": obj.get("paymentTerm"),
            "invoiceTemplateId": obj.get("invoiceTemplateId"),
            "amount": obj.get("amount"),
            "amountWithoutTax": obj.get("amountWithoutTax"),
            "itemNumber": obj.get("itemNumber"),
            "UOM": obj.get("UOM"),
            "amountPerUnit": obj.get("amountPerUnit"),
            "billTargetDate": obj.get("billTargetDate"),
            "billTo": obj.get("billTo"),
            "billToSnapshotId": obj.get("billToSnapshotId"),
            "billingRule": obj.get("billingRule") if obj.get("billingRule") is not None else OrderLineItemBillingRule.TRIGGERWITHOUTFULFILLMENT,
            "accountingCode": obj.get("accountingCode"),
            "adjustmentLiabilityAccountingCode": obj.get("adjustmentLiabilityAccountingCode"),
            "adjustmentRevenueAccountingCode": obj.get("adjustmentRevenueAccountingCode"),
            "contractAssetAccountingCode": obj.get("contractAssetAccountingCode"),
            "contractLiabilityAccountingCode": obj.get("contractLiabilityAccountingCode"),
            "contractRecognizedRevenueAccountingCode": obj.get("contractRecognizedRevenueAccountingCode"),
            "deferredRevenueAccountingCode": obj.get("deferredRevenueAccountingCode"),
            "customFields": obj.get("customFields"),
            "description": obj.get("description"),
            "discount": obj.get("discount"),
            "excludeItemBillingFromRevenueAccounting": obj.get("excludeItemBillingFromRevenueAccounting"),
            "excludeItemBookingFromRevenueAccounting": obj.get("excludeItemBookingFromRevenueAccounting"),
            "revenueRecognitionTiming": obj.get("revenueRecognitionTiming"),
            "revenueAmortizationMethod": obj.get("revenueAmortizationMethod"),
            "inlineDiscountPerUnit": obj.get("inlineDiscountPerUnit"),
            "inlineDiscountType": obj.get("inlineDiscountType"),
            "invoiceGroupNumber": obj.get("invoiceGroupNumber"),
            "invoiceOwnerAccountId": obj.get("invoiceOwnerAccountId"),
            "invoiceOwnerAccountName": obj.get("invoiceOwnerAccountName"),
            "invoiceOwnerAccountNumber": obj.get("invoiceOwnerAccountNumber"),
            "isAllocationEligible": obj.get("isAllocationEligible"),
            "isUnbilled": obj.get("isUnbilled"),
            "itemCategory": obj.get("itemCategory") if obj.get("itemCategory") is not None else OrderLineItemCategory.SALES,
            "itemName": obj.get("itemName"),
            "itemState": obj.get("itemState"),
            "itemType": obj.get("itemType"),
            "listPrice": obj.get("listPrice"),
            "listPricePerUnit": obj.get("listPricePerUnit"),
            "originalOrderId": obj.get("originalOrderId"),
            "originalOrderDate": obj.get("originalOrderDate"),
            "originalOrderLineItemId": obj.get("originalOrderLineItemId"),
            "originalOrderLineItemNumber": obj.get("originalOrderLineItemNumber"),
            "originalOrderNumber": obj.get("originalOrderNumber"),
            "ownerAccountId": obj.get("ownerAccountId"),
            "ownerAccountName": obj.get("ownerAccountName"),
            "ownerAccountNumber": obj.get("ownerAccountNumber"),
            "productCode": obj.get("productCode"),
            "productRatePlanChargeId": obj.get("productRatePlanChargeId"),
            "purchaseOrderNumber": obj.get("purchaseOrderNumber"),
            "quantity": obj.get("quantity"),
            "quantityAvailableForReturn": obj.get("quantityAvailableForReturn"),
            "quantityFulfilled": obj.get("quantityFulfilled"),
            "quantityPendingFulfillment": obj.get("quantityPendingFulfillment"),
            "recognizedRevenueAccountingCode": obj.get("recognizedRevenueAccountingCode"),
            "relatedSubscriptionNumber": obj.get("relatedSubscriptionNumber"),
            "requiresFulfillment": obj.get("requiresFulfillment"),
            "revenueRecognitionRule": obj.get("revenueRecognitionRule"),
            "sequenceSetId": obj.get("sequenceSetId"),
            "soldTo": obj.get("soldTo"),
            "soldToSnapshotId": obj.get("soldToSnapshotId"),
            "shipTo": obj.get("shipTo"),
            "shipToSnapshotId": obj.get("shipToSnapshotId"),
            "taxCode": obj.get("taxCode"),
            "taxMode": obj.get("taxMode"),
            "transactionEndDate": obj.get("transactionEndDate"),
            "transactionStartDate": obj.get("transactionStartDate"),
            "unbilledReceivablesAccountingCode": obj.get("unbilledReceivablesAccountingCode"),
            "fulfillments": [GetFulfillment.from_dict(_item) for _item in obj["fulfillments"]] if obj.get("fulfillments") is not None else None
        }
        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:])
