# coding: utf-8

"""
    Voucherify API

    Voucherify promotion engine REST API. Please see https://docs.voucherify.io/docs for more details.

    The version of the OpenAPI document: v2018-08-01
    Contact: support@voucherify.io
    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 datetime
from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from voucherify.models.member_activity_data_redemption_channel import MemberActivityDataRedemptionChannel
from voucherify.models.member_activity_data_redemption_order import MemberActivityDataRedemptionOrder
from voucherify.models.member_activity_data_redemption_previous_order import MemberActivityDataRedemptionPreviousOrder
from voucherify.models.member_activity_data_redemption_promotion_tier import MemberActivityDataRedemptionPromotionTier
from voucherify.models.member_activity_data_redemption_related_redemptions import MemberActivityDataRedemptionRelatedRedemptions
from voucherify.models.member_activity_data_redemption_reward import MemberActivityDataRedemptionReward
from voucherify.models.member_activity_data_redemption_voucher import MemberActivityDataRedemptionVoucher
from voucherify.models.simple_customer import SimpleCustomer
from typing import Optional, Set
from typing_extensions import Self

class MemberActivityDataRedemption(BaseModel):
    """
    MemberActivityDataRedemption
    """ # noqa: E501
    id: Optional[StrictStr] = Field(default=None, description="Unique redemption ID.")
    customer_id: Optional[StrictStr] = Field(default=None, description="Unique customer ID of the redeeming customer.")
    tracking_id: Optional[StrictStr] = Field(default=None, description="Hashed customer source ID.")
    var_date: Optional[datetime] = Field(default=None, description="Timestamp representing the date and time when the redemption was created in the ISO 8601 format.", alias="date")
    amount: Optional[StrictInt] = Field(default=None, description="For gift cards, this is a positive integer in the smallest currency unit (e.g. 100 cents for $1.00) representing the number of redeemed credits. For loyalty cards, this is the number of loyalty points used in the transaction. In the case of redemption rollback, the numbers are expressed as negative integers. and For gift cards, this is a positive integer in the smallest currency unit (e.g. 100 cents for $1.00) representing the number of redeemed credits. For loyalty cards, this is the number of loyalty points used in the transaction.")
    order: Optional[MemberActivityDataRedemptionOrder] = None
    reward: Optional[MemberActivityDataRedemptionReward] = None
    customer: Optional[SimpleCustomer] = None
    result: Optional[StrictStr] = Field(default=None, description="Redemption result.")
    status: Optional[StrictStr] = None
    voucher: Optional[MemberActivityDataRedemptionVoucher] = None
    promotion_tier: Optional[MemberActivityDataRedemptionPromotionTier] = None
    redemption: Optional[StrictStr] = Field(default=None, description="Unique redemption ID of the parent redemption.")
    metadata: Optional[Dict[str, Any]] = Field(default=None, description="The metadata object stores all custom attributes in the form of key/value pairs assigned to the redemption. and The metadata object stores all custom attributes assigned to the redemption.")
    failure_code: Optional[StrictStr] = Field(default=None, description="If the result is `FAILURE`, this parameter will provide a generic reason as to why the redemption failed.")
    failure_message: Optional[StrictStr] = None
    reason: Optional[StrictStr] = None
    channel: Optional[MemberActivityDataRedemptionChannel] = None
    object: Optional[StrictStr] = Field(default='redemption', description="The type of the object represented by the JSON. This object stores information about the `redemption`.")
    created_at: Optional[datetime] = Field(default=None, description="Timestamp representing the date and time when the redemption was created. The value is shown in the ISO 8601 format.")
    channel_type: Optional[StrictStr] = Field(default=None, description="The source of the channel for the redemption rollback. A `USER` corresponds to the Voucherify Dashboard and an `API` corresponds to the API.")
    channel_id: Optional[StrictStr] = Field(default=None, description="Unique channel ID of the user performing the redemption. This is either a user ID from a user using the Voucherify Dashboard or an X-APP-Id of a user using the API.")
    previous_order: Optional[MemberActivityDataRedemptionPreviousOrder] = None
    related_redemptions: Optional[MemberActivityDataRedemptionRelatedRedemptions] = None
    parent_redemption_id: Optional[StrictStr] = Field(default=None, description="Unique redemption ID of the parent redemption.")
    related_object_type: Optional[StrictStr] = Field(default=None, description="Defines the related object.")
    related_object_id: Optional[StrictStr] = Field(default=None, description="Unique related object ID assigned by Voucherify, i.e. v_lfZi4rcEGe0sN9gmnj40bzwK2FH6QUno for a voucher.")
    related_object_parent_id: Optional[StrictStr] = Field(default=None, description="Unique related parent object ID assigned by Voucherify, i.e. v_lfZi4rcEGe0sN9gmnj40bzwK2FH6QUno for a voucher.")
    campaign_name: Optional[StrictStr] = Field(default=None, description="Campaign name")
    __properties: ClassVar[List[str]] = ["id", "customer_id", "tracking_id", "date", "amount", "order", "reward", "customer", "result", "status", "voucher", "promotion_tier", "redemption", "metadata", "failure_code", "failure_message", "reason", "channel", "object", "created_at", "channel_type", "channel_id", "previous_order", "related_redemptions", "parent_redemption_id", "related_object_type", "related_object_id", "related_object_parent_id", "campaign_name"]

    @field_validator('result')
    def result_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['SUCCESS', 'FAILURE']):
            raise ValueError("must be one of enum values ('SUCCESS', 'FAILURE')")
        return value

    @field_validator('status')
    def status_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['SUCCEEDED', 'FAILED', 'ROLLED BACK']):
            raise ValueError("must be one of enum values ('SUCCEEDED', 'FAILED', 'ROLLED BACK')")
        return value

    @field_validator('channel_type')
    def channel_type_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['USER', 'API']):
            raise ValueError("must be one of enum values ('USER', 'API')")
        return value

    @field_validator('related_object_type')
    def related_object_type_validate_enum(cls, value):
        """Validates the enum"""
        if value is None:
            return value

        if value not in set(['voucher', 'promotion_tier']):
            raise ValueError("must be one of enum values ('voucher', 'promotion_tier')")
        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 MemberActivityDataRedemption 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 order
        if self.order:
            _dict['order'] = self.order.to_dict()
        # override the default output from pydantic by calling `to_dict()` of reward
        if self.reward:
            _dict['reward'] = self.reward.to_dict()
        # override the default output from pydantic by calling `to_dict()` of customer
        if self.customer:
            _dict['customer'] = self.customer.to_dict()
        # override the default output from pydantic by calling `to_dict()` of voucher
        if self.voucher:
            _dict['voucher'] = self.voucher.to_dict()
        # override the default output from pydantic by calling `to_dict()` of promotion_tier
        if self.promotion_tier:
            _dict['promotion_tier'] = self.promotion_tier.to_dict()
        # override the default output from pydantic by calling `to_dict()` of channel
        if self.channel:
            _dict['channel'] = self.channel.to_dict()
        # override the default output from pydantic by calling `to_dict()` of previous_order
        if self.previous_order:
            _dict['previous_order'] = self.previous_order.to_dict()
        # override the default output from pydantic by calling `to_dict()` of related_redemptions
        if self.related_redemptions:
            _dict['related_redemptions'] = self.related_redemptions.to_dict()
        # set to None if id (nullable) is None
        # and model_fields_set contains the field
        if self.id is None and "id" in self.model_fields_set:
            _dict['id'] = None

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of MemberActivityDataRedemption 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"),
            "customer_id": obj.get("customer_id"),
            "tracking_id": obj.get("tracking_id"),
            "date": obj.get("date"),
            "amount": obj.get("amount"),
            "order": MemberActivityDataRedemptionOrder.from_dict(obj["order"]) if obj.get("order") is not None else None,
            "reward": MemberActivityDataRedemptionReward.from_dict(obj["reward"]) if obj.get("reward") is not None else None,
            "customer": SimpleCustomer.from_dict(obj["customer"]) if obj.get("customer") is not None else None,
            "result": obj.get("result"),
            "status": obj.get("status"),
            "voucher": MemberActivityDataRedemptionVoucher.from_dict(obj["voucher"]) if obj.get("voucher") is not None else None,
            "promotion_tier": MemberActivityDataRedemptionPromotionTier.from_dict(obj["promotion_tier"]) if obj.get("promotion_tier") is not None else None,
            "redemption": obj.get("redemption"),
            "metadata": obj.get("metadata"),
            "failure_code": obj.get("failure_code"),
            "failure_message": obj.get("failure_message"),
            "reason": obj.get("reason"),
            "channel": MemberActivityDataRedemptionChannel.from_dict(obj["channel"]) if obj.get("channel") is not None else None,
            "object": obj.get("object") if obj.get("object") is not None else 'redemption',
            "created_at": obj.get("created_at"),
            "channel_type": obj.get("channel_type"),
            "channel_id": obj.get("channel_id"),
            "previous_order": MemberActivityDataRedemptionPreviousOrder.from_dict(obj["previous_order"]) if obj.get("previous_order") is not None else None,
            "related_redemptions": MemberActivityDataRedemptionRelatedRedemptions.from_dict(obj["related_redemptions"]) if obj.get("related_redemptions") is not None else None,
            "parent_redemption_id": obj.get("parent_redemption_id"),
            "related_object_type": obj.get("related_object_type"),
            "related_object_id": obj.get("related_object_id"),
            "related_object_parent_id": obj.get("related_object_parent_id"),
            "campaign_name": obj.get("campaign_name")
        })
        return _obj


