# 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, 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_fee import CdmFee
from acre_api.models.cdm_first_time_access import CdmFirstTimeAccess
from acre_api.models.cdm_lender_metadata import CdmLenderMetadata
from acre_api.models.cdm_metadata import CdmMetadata
from acre_api.models.cdm_note_template import CdmNoteTemplate
from acre_api.models.cdm_organisation_status import CdmOrganisationStatus
from acre_api.models.cdm_organisation_verification_class import CdmOrganisationVerificationClass
from acre_api.models.cdm_panel_management import CdmPanelManagement
from acre_api.models.cdm_periods_settings import CdmPeriodsSettings
from acre_api.models.cdm_process_settings import CdmProcessSettings
from acre_api.models.cdm_rmar_settings import CdmRMARSettings
from acre_api.models.cdm_schedule import CdmSchedule
from acre_api.models.cdm_standard_fee_options import CdmStandardFeeOptions
from acre_api.models.organisation_client_portal_settings import OrganisationClientPortalSettings
from acre_api.models.organisation_legal_form import OrganisationLegalForm
from acre_api.models.organisation_organisation_type import OrganisationOrganisationType
from typing import Optional, Set
from typing_extensions import Self

class CdmOrganisation(BaseModel):
    """
    Organisation describes an Acre organisation. All fields can be updated / set via the API unless otherwise stated.
    """ # noqa: E501
    organisation_id: Optional[StrictStr] = Field(default=None, description="UUID created by Acre. **IMPORTANT:** This field cannot be updated and is populated automatically.")
    organisation_ext_identifier: Optional[StrictStr] = Field(default=None, description="External UUID for Synchronisation. This external ID is converted into an internal ID that is populated in the \"organisation_id\" field. Ext identifiers must be scoped using the organisations domain name.")
    name: Optional[StrictStr] = None
    website: Optional[StrictStr] = None
    organisation_legal_form: Optional[OrganisationLegalForm] = OrganisationLegalForm.INVALID_LEGAL_FORM
    fca_reg_no: Optional[StrictStr] = None
    joined_acre: Optional[StrictStr] = None
    client_portal_url: Optional[StrictStr] = None
    representative_of: Optional[StrictStr] = Field(default=None, description="Which organisation holds this organisations regulation. Self referring if the organisation is directly authorisation.")
    representative_of_ext_identifier: Optional[StrictStr] = Field(default=None, description="External references of the representative organisations. This external ID is converted into an internal ID that is populated in the \"representative_of\" field. Ext identifiers must be scoped using the organisations domain name.")
    administered_by: Optional[StrictStr] = Field(default=None, description="If this is a subdivision, which organisation can manage this organisation.")
    administered_by_ext_identifier: Optional[StrictStr] = Field(default=None, description="External references of the managing organisations. This external ID is converted into an internal ID that is populated in the \"administered_by\" field. Ext identifiers must be scoped using the organisations domain name.")
    paid_by: Optional[StrictStr] = Field(default=None, description="Which organisation should be billed for this organisations usage.")
    paid_by_ext_identifier: Optional[StrictStr] = Field(default=None, description="External reference of billing organisation. This external ID is converted into an internal ID that is populated in the \"paid_by\" field. Ext identifiers must be scoped using the organisations domain name.")
    bank_details_sort_code: Optional[StrictStr] = None
    bank_details_account_no: Optional[StrictStr] = None
    primary_address: Optional[CdmAddress] = None
    primary_phone: Optional[StrictStr] = None
    complaints_address: Optional[CdmAddress] = None
    complaints_phone: Optional[StrictStr] = None
    complaints_url: Optional[StrictStr] = Field(default=None, description="URL for online complaints information / submission.")
    status: Optional[CdmOrganisationStatus] = CdmOrganisationStatus.INVALID_STATUS
    metadata: Optional[List[CdmMetadata]] = Field(default=None, description="Metadata regarding the organisation. Lender organisations must set \"twenty7tec_code\" and \"enbs_code\" to map product lender_codes to eNBS compatible codes.")
    fees: Optional[List[CdmFee]] = Field(default=None, description="Fees associated with the organisation.")
    standard_fee_options: Optional[List[CdmStandardFeeOptions]] = Field(default=None, description="Fee options associated with the organisation.")
    compliance_email: Optional[StrictStr] = Field(default=None, description="E-mail for receiving failed provisional competency notifications.")
    complaints_email: Optional[StrictStr] = Field(default=None, description="Email address for complaints.")
    modified_at: Optional[StrictStr] = Field(default=None, description="The datetime that the organisation was last modified (RFC3339).")
    general_email: Optional[StrictStr] = Field(default=None, description="General email address for sending emails from this organisation.")
    type: Optional[OrganisationOrganisationType] = OrganisationOrganisationType.INVALID_ORGANISATION_TYPE
    schedule: Optional[CdmSchedule] = None
    logo: Optional[StrictStr] = Field(default=None, description="Base64 encoded organisation logo.")
    panel_management: Optional[CdmPanelManagement] = None
    verification_class: Optional[CdmOrganisationVerificationClass] = None
    first_time_access: Optional[CdmFirstTimeAccess] = None
    note_templates: Optional[List[CdmNoteTemplate]] = Field(default=None, description="Note templates specify organisational note templates. These can not be deleted and can only be disabled.")
    credentials: Optional[List[CdmCredentials]] = Field(default=None, description="Third party credentials.")
    client_portal_settings: Optional[OrganisationClientPortalSettings] = None
    periods_settings: Optional[CdmPeriodsSettings] = None
    process_settings: Optional[CdmProcessSettings] = None
    lender_metadata: Optional[CdmLenderMetadata] = None
    rmar_settings: Optional[CdmRMARSettings] = None
    __properties: ClassVar[List[str]] = ["organisation_id", "organisation_ext_identifier", "name", "website", "organisation_legal_form", "fca_reg_no", "joined_acre", "client_portal_url", "representative_of", "representative_of_ext_identifier", "administered_by", "administered_by_ext_identifier", "paid_by", "paid_by_ext_identifier", "bank_details_sort_code", "bank_details_account_no", "primary_address", "primary_phone", "complaints_address", "complaints_phone", "complaints_url", "status", "metadata", "fees", "standard_fee_options", "compliance_email", "complaints_email", "modified_at", "general_email", "type", "schedule", "logo", "panel_management", "verification_class", "first_time_access", "note_templates", "credentials", "client_portal_settings", "periods_settings", "process_settings", "lender_metadata", "rmar_settings"]

    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 CdmOrganisation 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 primary_address
        if self.primary_address:
            _dict['primary_address'] = self.primary_address.to_dict()
        # override the default output from pydantic by calling `to_dict()` of complaints_address
        if self.complaints_address:
            _dict['complaints_address'] = self.complaints_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 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 schedule
        if self.schedule:
            _dict['schedule'] = self.schedule.to_dict()
        # override the default output from pydantic by calling `to_dict()` of panel_management
        if self.panel_management:
            _dict['panel_management'] = self.panel_management.to_dict()
        # override the default output from pydantic by calling `to_dict()` of verification_class
        if self.verification_class:
            _dict['verification_class'] = self.verification_class.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 note_templates (list)
        _items = []
        if self.note_templates:
            for _item_note_templates in self.note_templates:
                if _item_note_templates:
                    _items.append(_item_note_templates.to_dict())
            _dict['note_templates'] = _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 client_portal_settings
        if self.client_portal_settings:
            _dict['client_portal_settings'] = self.client_portal_settings.to_dict()
        # override the default output from pydantic by calling `to_dict()` of periods_settings
        if self.periods_settings:
            _dict['periods_settings'] = self.periods_settings.to_dict()
        # override the default output from pydantic by calling `to_dict()` of process_settings
        if self.process_settings:
            _dict['process_settings'] = self.process_settings.to_dict()
        # override the default output from pydantic by calling `to_dict()` of lender_metadata
        if self.lender_metadata:
            _dict['lender_metadata'] = self.lender_metadata.to_dict()
        # override the default output from pydantic by calling `to_dict()` of rmar_settings
        if self.rmar_settings:
            _dict['rmar_settings'] = self.rmar_settings.to_dict()
        return _dict

    @classmethod
    def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
        """Create an instance of CdmOrganisation 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"),
            "name": obj.get("name"),
            "website": obj.get("website"),
            "organisation_legal_form": obj.get("organisation_legal_form") if obj.get("organisation_legal_form") is not None else OrganisationLegalForm.INVALID_LEGAL_FORM,
            "fca_reg_no": obj.get("fca_reg_no"),
            "joined_acre": obj.get("joined_acre"),
            "client_portal_url": obj.get("client_portal_url"),
            "representative_of": obj.get("representative_of"),
            "representative_of_ext_identifier": obj.get("representative_of_ext_identifier"),
            "administered_by": obj.get("administered_by"),
            "administered_by_ext_identifier": obj.get("administered_by_ext_identifier"),
            "paid_by": obj.get("paid_by"),
            "paid_by_ext_identifier": obj.get("paid_by_ext_identifier"),
            "bank_details_sort_code": obj.get("bank_details_sort_code"),
            "bank_details_account_no": obj.get("bank_details_account_no"),
            "primary_address": CdmAddress.from_dict(obj["primary_address"]) if obj.get("primary_address") is not None else None,
            "primary_phone": obj.get("primary_phone"),
            "complaints_address": CdmAddress.from_dict(obj["complaints_address"]) if obj.get("complaints_address") is not None else None,
            "complaints_phone": obj.get("complaints_phone"),
            "complaints_url": obj.get("complaints_url"),
            "status": obj.get("status") if obj.get("status") is not None else CdmOrganisationStatus.INVALID_STATUS,
            "metadata": [CdmMetadata.from_dict(_item) for _item in obj["metadata"]] if obj.get("metadata") 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,
            "compliance_email": obj.get("compliance_email"),
            "complaints_email": obj.get("complaints_email"),
            "modified_at": obj.get("modified_at"),
            "general_email": obj.get("general_email"),
            "type": obj.get("type") if obj.get("type") is not None else OrganisationOrganisationType.INVALID_ORGANISATION_TYPE,
            "schedule": CdmSchedule.from_dict(obj["schedule"]) if obj.get("schedule") is not None else None,
            "logo": obj.get("logo"),
            "panel_management": CdmPanelManagement.from_dict(obj["panel_management"]) if obj.get("panel_management") is not None else None,
            "verification_class": CdmOrganisationVerificationClass.from_dict(obj["verification_class"]) if obj.get("verification_class") 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,
            "note_templates": [CdmNoteTemplate.from_dict(_item) for _item in obj["note_templates"]] if obj.get("note_templates") is not None else None,
            "credentials": [CdmCredentials.from_dict(_item) for _item in obj["credentials"]] if obj.get("credentials") is not None else None,
            "client_portal_settings": OrganisationClientPortalSettings.from_dict(obj["client_portal_settings"]) if obj.get("client_portal_settings") is not None else None,
            "periods_settings": CdmPeriodsSettings.from_dict(obj["periods_settings"]) if obj.get("periods_settings") is not None else None,
            "process_settings": CdmProcessSettings.from_dict(obj["process_settings"]) if obj.get("process_settings") is not None else None,
            "lender_metadata": CdmLenderMetadata.from_dict(obj["lender_metadata"]) if obj.get("lender_metadata") is not None else None,
            "rmar_settings": CdmRMARSettings.from_dict(obj["rmar_settings"]) if obj.get("rmar_settings") is not None else None
        })
        return _obj


