# coding: utf-8

"""
    Acre Platform User API

    # CORS CORS is implemented by all Acre API endpoints and only certain hostnames are allowed for each deployment of the API. If your use case requires calling the Acre User API from a browser, please contact Acre to arrange the appropriate configuration. # API Authentication The primary method of authentication for users of the Acre API is with the use of JSON Web Tokens (JWTs), which are suplemented by an application specific API Key. The API key must be provided through the `X-API-KEY` HTTP header and will be provided by your Acre Customer Success Manager. The JWT must be provided through a cookie with key of `authorization`. The JWT must be generated and signed as per the following section. # Generating JWTs JWT must either be generated by a third-party such as Azure ADB2C that has been configured for the appropriate service and/or user account, or alternatively can be generated locally and signed by an private key for which the public key has been made available to Acre via a JWKS URL. In addition to being signed by your private key, the JWT will also need to contain at a minimum:  * An issuer `iss`, which must be a valid URI previously agreed with Acre.  * A subject `sub`, which must be a unique identifier for the user and/or service account previously agreed with Acre.  * An expiry time `exp` which must not be more than four hours in the future.  * A not before time `nbf` which must be in the past, but not greater than six hours in the past.  The JWT should be signed using RS256.

    The version of the OpenAPI document: 1.0
    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 pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from acre_api.models.cdm_address import CdmAddress
from acre_api.models.cdm_credentials import CdmCredentials
from acre_api.models.cdm_employment_basis import CdmEmploymentBasis
from acre_api.models.cdm_external import CdmExternal
from acre_api.models.cdm_fee import CdmFee
from acre_api.models.cdm_first_time_access import CdmFirstTimeAccess
from acre_api.models.cdm_metadata import CdmMetadata
from acre_api.models.cdm_schedule import CdmSchedule
from acre_api.models.cdm_standard_fee_options import CdmStandardFeeOptions
from acre_api.models.cdm_training_and_competency import CdmTrainingAndCompetency
from acre_api.models.cdm_user_authentication import CdmUserAuthentication
from acre_api.models.cdm_user_status import CdmUserStatus
from typing import Optional, Set
from typing_extensions import Self

class PartialDetailsOfTheUserToBePatchedRequired(BaseModel):
    """
    PartialDetailsOfTheUserToBePatchedRequired
    """ # noqa: E501
    organisation_id: Optional[StrictStr] = Field(default=None, description="Organisation reference using the acre ID. Included in summary.")
    organisation_ext_identifier: Optional[StrictStr] = Field(default=None, description="Organisation reference using the external ID.")
    user_firm_identifier: Optional[StrictStr] = Field(default=None, description="Firm identifier for user (e.g., employee number). This is an external identifier, *NOT* an Acre ID.")
    first_name: Optional[StrictStr] = Field(default=None, description="First name of user. This is equivalent to a given name. Included in summary.")
    last_name: Optional[StrictStr] = Field(default=None, description="Last name of user. This is equivalent to a family name. Included in summary.")
    address: Optional[CdmAddress] = None
    email_address: Optional[StrictStr] = Field(default=None, description="User e-mail address for contact and login. Included in summary.")
    phone_mobile: Optional[StrictStr] = Field(default=None, description="Users mobile phone number. Included in summary.")
    phone_desk: Optional[StrictStr] = Field(default=None, description="Users desk phone number. Included in summary.")
    status: Optional[CdmUserStatus] = CdmUserStatus.INVALID_STATUS
    inactive_date: Optional[StrictStr] = Field(default=None, description="The date when the user was last made DISABLED (RFC3339). **IMPORTANT:** This field is populated automatically. If the user gets enabled again, this doesn't get removed. If then it gets disabled again, the date will be overwritten.")
    primary_role_id: Optional[StrictStr] = Field(default=None, description="User's primary role. This field must exactly match the name of an existing role. Included in summary.")
    metadata: Optional[List[CdmMetadata]] = Field(default=None, description="Metadata regarding the user.")
    authentications: Optional[List[CdmUserAuthentication]] = Field(default=None, description="Methods for authenticating the user.")
    fees: Optional[List[CdmFee]] = Field(default=None, description="Fees associated with the user.")
    standard_fee_options: Optional[List[CdmStandardFeeOptions]] = Field(default=None, description="Fee options associated with the user.")
    group_ids: Optional[List[StrictStr]] = Field(default=None, description="Other groups the user holds. This field must contain a list of group ids, each of which exactly matches an existing group id.")
    modified_at: Optional[StrictStr] = None
    credentials: Optional[List[CdmCredentials]] = Field(default=None, description="User credentials. Can only be updated by user to whom they belong. Note: when updating send ids for all elements that should be kept (data will be pulled from old version) and only the fields that are changing.")
    schedule: Optional[CdmSchedule] = None
    first_time_access: Optional[CdmFirstTimeAccess] = None
    external: Optional[List[CdmExternal]] = Field(default=None, description="Identifiers for the user in third-party systems.")
    photo: Optional[StrictStr] = Field(default=None, description="A base64 encoded photograph.")
    training_and_competency: Optional[CdmTrainingAndCompetency] = None
    employment_basis: Optional[CdmEmploymentBasis] = CdmEmploymentBasis.INVALID_EMPLOYED_BASIS
    part_time_percentage: Optional[StrictInt] = Field(default=None, description="Percentage of part time hours. The value must be a number between 1 and 99 and it's mandatory if employment_basis is PART_TIME.")
    __properties: ClassVar[List[str]] = ["organisation_id", "organisation_ext_identifier", "user_firm_identifier", "first_name", "last_name", "address", "email_address", "phone_mobile", "phone_desk", "status", "inactive_date", "primary_role_id", "metadata", "authentications", "fees", "standard_fee_options", "group_ids", "modified_at", "credentials", "schedule", "first_time_access", "external", "photo", "training_and_competency", "employment_basis", "part_time_percentage"]

    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 PartialDetailsOfTheUserToBePatchedRequired 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 address
        if self.address:
            _dict['address'] = self.address.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in metadata (list)
        _items = []
        if self.metadata:
            for _item_metadata in self.metadata:
                if _item_metadata:
                    _items.append(_item_metadata.to_dict())
            _dict['metadata'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in authentications (list)
        _items = []
        if self.authentications:
            for _item_authentications in self.authentications:
                if _item_authentications:
                    _items.append(_item_authentications.to_dict())
            _dict['authentications'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in fees (list)
        _items = []
        if self.fees:
            for _item_fees in self.fees:
                if _item_fees:
                    _items.append(_item_fees.to_dict())
            _dict['fees'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in standard_fee_options (list)
        _items = []
        if self.standard_fee_options:
            for _item_standard_fee_options in self.standard_fee_options:
                if _item_standard_fee_options:
                    _items.append(_item_standard_fee_options.to_dict())
            _dict['standard_fee_options'] = _items
        # override the default output from pydantic by calling `to_dict()` of each item in credentials (list)
        _items = []
        if self.credentials:
            for _item_credentials in self.credentials:
                if _item_credentials:
                    _items.append(_item_credentials.to_dict())
            _dict['credentials'] = _items
        # override the default output from pydantic by calling `to_dict()` of schedule
        if self.schedule:
            _dict['schedule'] = self.schedule.to_dict()
        # override the default output from pydantic by calling `to_dict()` of first_time_access
        if self.first_time_access:
            _dict['first_time_access'] = self.first_time_access.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in external (list)
        _items = []
        if self.external:
            for _item_external in self.external:
                if _item_external:
                    _items.append(_item_external.to_dict())
            _dict['external'] = _items
        # override the default output from pydantic by calling `to_dict()` of training_and_competency
        if self.training_and_competency:
            _dict['training_and_competency'] = self.training_and_competency.to_dict()
        return _dict

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

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

        _obj = cls.model_validate({
            "organisation_id": obj.get("organisation_id"),
            "organisation_ext_identifier": obj.get("organisation_ext_identifier"),
            "user_firm_identifier": obj.get("user_firm_identifier"),
            "first_name": obj.get("first_name"),
            "last_name": obj.get("last_name"),
            "address": CdmAddress.from_dict(obj["address"]) if obj.get("address") is not None else None,
            "email_address": obj.get("email_address"),
            "phone_mobile": obj.get("phone_mobile"),
            "phone_desk": obj.get("phone_desk"),
            "status": obj.get("status") if obj.get("status") is not None else CdmUserStatus.INVALID_STATUS,
            "inactive_date": obj.get("inactive_date"),
            "primary_role_id": obj.get("primary_role_id"),
            "metadata": [CdmMetadata.from_dict(_item) for _item in obj["metadata"]] if obj.get("metadata") is not None else None,
            "authentications": [CdmUserAuthentication.from_dict(_item) for _item in obj["authentications"]] if obj.get("authentications") is not None else None,
            "fees": [CdmFee.from_dict(_item) for _item in obj["fees"]] if obj.get("fees") is not None else None,
            "standard_fee_options": [CdmStandardFeeOptions.from_dict(_item) for _item in obj["standard_fee_options"]] if obj.get("standard_fee_options") is not None else None,
            "group_ids": obj.get("group_ids"),
            "modified_at": obj.get("modified_at"),
            "credentials": [CdmCredentials.from_dict(_item) for _item in obj["credentials"]] if obj.get("credentials") is not None else None,
            "schedule": CdmSchedule.from_dict(obj["schedule"]) if obj.get("schedule") is not None else None,
            "first_time_access": CdmFirstTimeAccess.from_dict(obj["first_time_access"]) if obj.get("first_time_access") is not None else None,
            "external": [CdmExternal.from_dict(_item) for _item in obj["external"]] if obj.get("external") is not None else None,
            "photo": obj.get("photo"),
            "training_and_competency": CdmTrainingAndCompetency.from_dict(obj["training_and_competency"]) if obj.get("training_and_competency") is not None else None,
            "employment_basis": obj.get("employment_basis") if obj.get("employment_basis") is not None else CdmEmploymentBasis.INVALID_EMPLOYED_BASIS,
            "part_time_percentage": obj.get("part_time_percentage")
        })
        return _obj


