# 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, StrictBool, StrictFloat, StrictInt, StrictStr
from typing import Any, ClassVar, Dict, List, Optional, Union
from acre_api.models.cdm_mortgage_type import CdmMortgageType
from acre_api.models.cdm_reason_for_mortgage import CdmReasonForMortgage
from acre_api.models.cdm_source_applicant import CdmSourceApplicant
from acre_api.models.cdm_source_details_property_tenure import CdmSourceDetailsPropertyTenure
from acre_api.models.cdm_source_details_property_type import CdmSourceDetailsPropertyType
from acre_api.models.cdm_source_details_term_unit import CdmSourceDetailsTermUnit
from acre_api.models.source_details_buy_to_let_refurbishment_type import SourceDetailsBuyToLetRefurbishmentType
from acre_api.models.source_details_landlord_status import SourceDetailsLandlordStatus
from acre_api.models.source_details_payment_method import SourceDetailsPaymentMethod
from acre_api.models.source_details_reason_for_remortgage import SourceDetailsReasonForRemortgage
from acre_api.models.source_details_search_matching_type import SourceDetailsSearchMatchingType
from acre_api.models.source_details_sort_column import SourceDetailsSortColumn
from acre_api.models.source_details_tenant_status import SourceDetailsTenantStatus
from typing import Optional, Set
from typing_extensions import Self

class CdmSourceDetails(BaseModel):
    """
    CdmSourceDetails
    """ # noqa: E501
    term: Optional[StrictInt] = Field(default=None, description="Mortgage Term required. This field works in conjunction with the TermUnit field.")
    expected_valuation: Optional[StrictInt] = Field(default=None, description="Purchase Price / Property Value.")
    loan_required: Optional[StrictInt] = Field(default=None, description="Loan amount required.")
    reason_for_mortgage: Optional[CdmReasonForMortgage] = CdmReasonForMortgage.INVALID_REASON_FOR_MORTGAGE
    remortgage_reason: Optional[SourceDetailsReasonForRemortgage] = SourceDetailsReasonForRemortgage.INVALID_REASON_FOR_REMORTGAGE
    mortgage_type: Optional[CdmMortgageType] = CdmMortgageType.INVALID_MORTGAGE_TYPE
    buy_to_let_expected_rental_income_per_month: Optional[StrictInt] = Field(default=None, description="How much will the rental income be from the property.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_number_of_properties_owned_excluding_own_residence: Optional[StrictInt] = Field(default=None, description="How many properties does the client own in addition to their main residence.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_total_borrowing_on_properties_excluding_own_residence: Optional[StrictInt] = Field(default=None, description="The total mortgage amount outstanding on the properties owned except the main residence.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_number_of_floors: Optional[StrictInt] = Field(default=None, description="The number of floors in the block if a flat.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_shorthold_tenancy_agreement: Optional[StrictBool] = Field(default=None, description="Indicates if a Shorthold Tenancy is required for the property.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_shorthold_tenancy_agreements_total_for_property: Optional[StrictInt] = Field(default=None, description="Indicates the value of the Shorthold Tenancy.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_number_of_tenants: Optional[StrictInt] = Field(default=None, description="The maximum number of tenants.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_tenant_status: Optional[SourceDetailsTenantStatus] = SourceDetailsTenantStatus.INVALID_TENANT_STATUS
    buy_to_let_corporate_let: Optional[StrictBool] = Field(default=None, description="Indicates if let to a company.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_house_of_multiple_occupancy: Optional[StrictBool] = Field(default=None, description="Indicates if let to a house of multiple occupancy.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_bedsit: Optional[StrictBool] = Field(default=None, description="Indicates if the property is a bedsit.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_bedsit_number_of_rooms: Optional[StrictInt] = Field(default=None, description="The number of rooms in the bedsit.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_limited_company: Optional[StrictBool] = Field(default=None, description="Indicates if the owner is a limited company.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_limited_company_spv: Optional[StrictBool] = Field(default=None, description="Indicates if the owner is a limited company special purpose vehicle.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_landlord_status: Optional[SourceDetailsLandlordStatus] = SourceDetailsLandlordStatus.INVALID_LANDLORD_STATUS
    buy_to_let_refurbishment_type: Optional[SourceDetailsBuyToLetRefurbishmentType] = SourceDetailsBuyToLetRefurbishmentType.INVALID_BTL_REFURBISHMENT_TYPE
    buy_to_let_property_occupied_by_family_member: Optional[StrictBool] = Field(default=None, description="Indicates whether the property will be occupied by a family member, used in determining regulated BTL.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_consumer: Optional[StrictBool] = Field(default=None, description="Indicates whether this search is for a Consumer Buy To Let.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_consumer_regulated: Optional[StrictBool] = Field(default=None, description="When the buy_to_let_consumer field is set to Yes, then this flag will further indicate whether this search is for a Consumer Regulated Buy To Let.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_limited_company_name: Optional[StrictStr] = Field(default=None, description="The name of the limited company. This value will be used as the client name for document production when either the buy_to_let_limited_company or buy_to_let_limited_company_spv value is set as ‘Yes’.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_applicants_are_high_tax_rate_payers: Optional[StrictBool] = Field(default=None, description="Indicates whether the applicants are high tax rate payers, which will impact the BTL rental income calculation rate used for establishing whether products are available for the expected rental income provided.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.")
    buy_to_let_allows_top_slicing: Optional[StrictBool] = Field(default=None, description="Indicates whether to allow top slicing products that skip the BTL rental income calculations for those products.  May only be provided if mortgage_type is MORTGAGE_BUY_TO_LET.  int32 right_to_buy_discounted_purchase_price = 35; enum ReasonsLoanRequiredGreaterThanDiscountedPurchasePrice {  INVALID_REASONS_LOAN_REQUIRED = 0;  REASONS_LOAN_REQUIRED_CAPITAL_RAISING = 1;  REASONS_LOAN_REQUIRED_DEBT_CONSOLIDATION = 2;  REASONS_LOAN_REQUIRED_HOME_IMPROVEMENTS = 3;  REASONS_LOAN_REQUIRED_LEGAL_EXPENSES = 4; }")
    payment_method: Optional[SourceDetailsPaymentMethod] = SourceDetailsPaymentMethod.INVALID_PAYMENT_METHOD
    part_investment_loan_required_investment_part: Optional[StrictInt] = Field(default=None, description="The interest only part of the loan when the repayment method is part and part/Split.  Address property_details_address = 61;")
    property_postcode: Optional[StrictStr] = Field(default=None, description="The subject address postcode. If a specific property postcode is not provided, you can restrict the product results to a region by providing one of the following values for this field: XE = England XI = Northern Ireland XS = Scotland XW = Wales.")
    property_type: Optional[CdmSourceDetailsPropertyType] = CdmSourceDetailsPropertyType.INVALID_PROPERTY_TYPE
    property_tenure: Optional[CdmSourceDetailsPropertyTenure] = CdmSourceDetailsPropertyTenure.INVALID_PROPERTY_TENURE
    mortgage_class_fixed: Optional[StrictBool] = Field(default=None, description="Option to filter against fixed products.")
    mortgage_class_variable: Optional[StrictBool] = Field(default=None, description="Option to filter against variable products.")
    mortgage_class_capped: Optional[StrictBool] = Field(default=None, description="Option to filter against Capped products.")
    mortgage_class_libor_linked: Optional[StrictBool] = Field(default=None, description="Option to filter against LIBOR products.")
    mortgage_class_discount: Optional[StrictBool] = Field(default=None, description="Option to filter against discount products.")
    mortgage_class_tracker: Optional[StrictBool] = Field(default=None, description="Option to filter against Tracker products.")
    filter_cashback: Optional[StrictBool] = Field(default=None, description="Option to filter against products that have a cashback incentive products.")
    filter_product_term_period_from_months: Optional[StrictInt] = Field(default=None, description="Option to select in months the time a product rate period starts.")
    filter_product_term_period_to_months: Optional[StrictInt] = Field(default=None, description="Option to select in months the time a product rate period ends.")
    filter_free_legal_fees: Optional[StrictBool] = Field(default=None, description="Option to filter against products that offer free legal fees as an incentive.")
    filter_free_lender_fees: Optional[StrictBool] = Field(default=None, description="Option to filter against products that have no lender fees.")
    filter_max_acceptable_arrangement_fee: Optional[StrictInt] = Field(default=None, description="Used to filter out products that have an arrangement fee that is greater than this value.")
    filter_max_acceptable_total_fees: Optional[StrictInt] = Field(default=None, description="Used to filter out products that have a total fees amount greater than this value.")
    filter_no_erc_payable: Optional[StrictBool] = Field(default=None, description="Option to filter against products where there is no ERC payable.")
    filter_erc_payable_after_initial_period: Optional[StrictBool] = Field(default=None, description="Option to filter against products where there is no ERC payable after the initial period.")
    filter_ccjs_acceptable: Optional[StrictBool] = Field(default=None, description="Option to filter against CCJs being acceptable for a product.")
    filter_ivas_acceptable: Optional[StrictBool] = Field(default=None, description="Option to filter against IVAs being acceptable for a product.")
    filter_bankruptcy_acceptable: Optional[StrictBool] = Field(default=None, description="Option to filter against Bankrupcy being acceptable for a product.")
    filter_arrears_acceptable: Optional[StrictBool] = Field(default=None, description="Option to filter against Arrears being acceptable for a product.")
    filter_defaults_acceptable: Optional[StrictBool] = Field(default=None, description="Option to filter against Defaults being acceptable for a product.")
    filter_dmps_acceptable: Optional[StrictBool] = Field(default=None, description="Option to filter against Debt Management Plans being acceptable for a product.")
    filter_payday_loans_acceptable: Optional[StrictBool] = Field(default=None, description="Option to filter against Payday Loans being acceptable for a product.")
    filter_is_offset: Optional[StrictBool] = Field(default=None, description="Filter filter_repossessions_acceptable = 94; Option to filter out products based on being classified as Offset.")
    filter_no_stepped: Optional[StrictBool] = Field(default=None, description="Option to filter out products based on having a stepped rate.")
    filter_help_to_buy: Optional[StrictBool] = Field(default=None, description="Option to filter out products based on having a product type of HelpToBuy.")
    filter_help_to_buy_shared_equity: Optional[StrictBool] = Field(default=None, description="Filter filter_help_to_buy_mortgage_guarantee = 99;")
    filter_valuation_fee: Optional[StrictBool] = Field(default=None, description="Option to filter out products based on having a valuation fee. When this filter is set to Include, it will only return products that have a valuation fee. If the intent is to only return products with NO valuation fee, then this should be set to Ignore.")
    filter_overpayments_allowed: Optional[StrictBool] = Field(default=None, description="Option to filter out products based on allowing overpayments.")
    filter_higher_lending_charge: Optional[StrictBool] = Field(default=None, description="Option to filter out products based on having a higher lending charge.")
    filter_direct: Optional[StrictBool] = Field(default=None, description="Option to filter direct products.")
    filter_included_lenders: Optional[List[StrictStr]] = None
    filter_excluded_lenders: Optional[List[StrictStr]] = None
    filter_sort_results_by_column: Optional[SourceDetailsSortColumn] = None
    filter_guarantors: Optional[StrictBool] = Field(default=None, description="Option to filter products that allow guarantors.")
    filter_portable: Optional[StrictBool] = Field(default=None, description="Option to filter products that are portable.")
    filter_no_arrangement_fee: Optional[StrictBool] = Field(default=None, description="Option to filter products that don’t have an arrangement fee.")
    filter_no_booking_fee: Optional[StrictBool] = Field(default=None, description="Option to filter products that don’t have a booking fee.")
    filter_refunded_valuation_fees: Optional[StrictBool] = Field(default=None, description="Option to filter products that have refunded valuation fees.")
    filter_loyalty: Optional[StrictBool] = Field(default=None, description="Option to filter products that are loyalty products.")
    filter_retention: Optional[StrictBool] = Field(default=None, description="Option to filter products that are retention products.")
    filter_refunded_legal_fees: Optional[StrictBool] = Field(default=None, description="Option to filter products that have refunded legal fees.")
    filter_exclusive: Optional[StrictBool] = Field(default=None, description="Option to filter products that have refunded legal fees.  repeated string filter_included_packagers = 115; Filter filter_allow_top_slicing = 116; int32 filter_min_acceptable_total_fees = 117; int32 filter_min_acceptable_arrangement_fee = 118; enum DepositSource {  INVALID_DEPOSIT_SOURCE = 0;  DEPOSIT_BUILDERS_GIFT = 1;  DEPOSIT_GIFT = 2;  DEPOSIT_LOAN = 3;  DEPOSIT_SAVINGS = 4;  DEPOSIT_SALE_OF_PROPERTY = 5;  DEPOSIT_INHERITANCE = 6;  DEPOSIT_VENDOR_GIFTED = 7;  DEPOSIT_EQUITY = 8;  DEPOSIT_SALE_OF_OTHER_PROPERTY = 9;  DEPOSIT_IMMEDIATE_FAMILY_GIFT = 10; } DepositSource deposit_source = 119;")
    applicants: Optional[List[CdmSourceApplicant]] = Field(default=None, description="Applicants for the mortgage.")
    true_cost_calculate_over_no_of_months: Optional[StrictInt] = Field(default=None, description="This field defines the Number of Months the True Cost is to be calculated over. If a value is specified for this field then the resulting calculation will be returned in the TrueCost field of the results object.")
    true_cost_disable_calculate_over_initial_period: Optional[StrictBool] = Field(default=None, description="Indicates if the True Cost is to be calculated over the product’s initial rate period. If a value of false (default) is provided, then the result of this calculation will be returned in the TrueCostOverInitialPeriod field of the results object.")
    true_cost_disable_add_fees_that_will_be_added_to_loan: Optional[StrictBool] = Field(default=None, description="When this value is set to false (default), fees that will or can be added to the loan are included in the True Cost calculation. When this value is set to true, then fees are not included in the TrueCost calculation.")
    true_cost_disable_add_fees_payable_to_true_cost_total: Optional[StrictBool] = Field(default=None, description="When this value is set to false (default), then fees payable (fees that can’t be added to the loan) are included in the True Cost Calculation. When this value is true then fees payable are not included in the TrueCost calculation.")
    true_cost_disable_deduct_cashback: Optional[StrictBool] = Field(default=None, description="False (default) indicates the product cashback will be deducted from the True Cost Calculation.")
    true_cost_disable_deduct_refunded_fees: Optional[StrictBool] = Field(default=None, description="False (default) indicates the refunded fees will be deducted from the True Cost Calculation.")
    true_cost_pay_broker_fee_up_front: Optional[StrictBool] = Field(default=None, description="When sourcing Bridging Loans or Secured Loans, this field can be set to indicate whether the broker fee should be excluded from being added to the loan in the TrueCost calculation and will instead be paid up front. This value is only considered when ‘AddFeesThatWillBeAddedToLoan’ is set to true.")
    true_cost_pay_arrangement_fee_up_front: Optional[StrictBool] = Field(default=None, description="When sourcing Bridging Loans or Secured Loans, this field can be set to indicate whether the arrangement fee should be excluded from being added to the loan in the TrueCost calculation and will instead be paid up front. This value is only considered when ‘AddFeesThatWillBeAddedToLoan’ is set to true.  bool true_cost_include_valuation_fee = 129; bool true_cost_include_mortgage_discharge_fee = 130; bool true_cost_include_deeds_release_fee = 131; bool true_cost_include_higher_lending_charge = 132; bool true_cost_include_booking_fee = 133; bool true_cost_include_broker_fee = 134; bool true_cost_include_disbursement_fee = 135;")
    number_of_items: Optional[StrictInt] = Field(default=None, description="Max number of items to return in the result set.")
    term_unit: Optional[CdmSourceDetailsTermUnit] = CdmSourceDetailsTermUnit.INVALID_TERM_UNIT
    search_matching_type: Optional[SourceDetailsSearchMatchingType] = SourceDetailsSearchMatchingType.INVALID_SEARCH_MATCHING_TYPE
    stress_test_number_of_increments: Optional[StrictInt] = Field(default=None, description="Specifies the number of increments to calculate. This value must be between 0 and 20.")
    stress_test_rate_increment_percent: Optional[Union[StrictFloat, StrictInt]] = None
    exclude_retention: Optional[StrictBool] = Field(default=None, description="Option to exclude retention products on sourcing.")
    __properties: ClassVar[List[str]] = ["term", "expected_valuation", "loan_required", "reason_for_mortgage", "remortgage_reason", "mortgage_type", "buy_to_let_expected_rental_income_per_month", "buy_to_let_number_of_properties_owned_excluding_own_residence", "buy_to_let_total_borrowing_on_properties_excluding_own_residence", "buy_to_let_number_of_floors", "buy_to_let_shorthold_tenancy_agreement", "buy_to_let_shorthold_tenancy_agreements_total_for_property", "buy_to_let_number_of_tenants", "buy_to_let_tenant_status", "buy_to_let_corporate_let", "buy_to_let_house_of_multiple_occupancy", "buy_to_let_bedsit", "buy_to_let_bedsit_number_of_rooms", "buy_to_let_limited_company", "buy_to_let_limited_company_spv", "buy_to_let_landlord_status", "buy_to_let_refurbishment_type", "buy_to_let_property_occupied_by_family_member", "buy_to_let_consumer", "buy_to_let_consumer_regulated", "buy_to_let_limited_company_name", "buy_to_let_applicants_are_high_tax_rate_payers", "buy_to_let_allows_top_slicing", "payment_method", "part_investment_loan_required_investment_part", "property_postcode", "property_type", "property_tenure", "mortgage_class_fixed", "mortgage_class_variable", "mortgage_class_capped", "mortgage_class_libor_linked", "mortgage_class_discount", "mortgage_class_tracker", "filter_cashback", "filter_product_term_period_from_months", "filter_product_term_period_to_months", "filter_free_legal_fees", "filter_free_lender_fees", "filter_max_acceptable_arrangement_fee", "filter_max_acceptable_total_fees", "filter_no_erc_payable", "filter_erc_payable_after_initial_period", "filter_ccjs_acceptable", "filter_ivas_acceptable", "filter_bankruptcy_acceptable", "filter_arrears_acceptable", "filter_defaults_acceptable", "filter_dmps_acceptable", "filter_payday_loans_acceptable", "filter_is_offset", "filter_no_stepped", "filter_help_to_buy", "filter_help_to_buy_shared_equity", "filter_valuation_fee", "filter_overpayments_allowed", "filter_higher_lending_charge", "filter_direct", "filter_included_lenders", "filter_excluded_lenders", "filter_sort_results_by_column", "filter_guarantors", "filter_portable", "filter_no_arrangement_fee", "filter_no_booking_fee", "filter_refunded_valuation_fees", "filter_loyalty", "filter_retention", "filter_refunded_legal_fees", "filter_exclusive", "applicants", "true_cost_calculate_over_no_of_months", "true_cost_disable_calculate_over_initial_period", "true_cost_disable_add_fees_that_will_be_added_to_loan", "true_cost_disable_add_fees_payable_to_true_cost_total", "true_cost_disable_deduct_cashback", "true_cost_disable_deduct_refunded_fees", "true_cost_pay_broker_fee_up_front", "true_cost_pay_arrangement_fee_up_front", "number_of_items", "term_unit", "search_matching_type", "stress_test_number_of_increments", "stress_test_rate_increment_percent", "exclude_retention"]

    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 CdmSourceDetails 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 filter_sort_results_by_column
        if self.filter_sort_results_by_column:
            _dict['filter_sort_results_by_column'] = self.filter_sort_results_by_column.to_dict()
        # override the default output from pydantic by calling `to_dict()` of each item in applicants (list)
        _items = []
        if self.applicants:
            for _item_applicants in self.applicants:
                if _item_applicants:
                    _items.append(_item_applicants.to_dict())
            _dict['applicants'] = _items
        return _dict

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

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

        _obj = cls.model_validate({
            "term": obj.get("term"),
            "expected_valuation": obj.get("expected_valuation"),
            "loan_required": obj.get("loan_required"),
            "reason_for_mortgage": obj.get("reason_for_mortgage") if obj.get("reason_for_mortgage") is not None else CdmReasonForMortgage.INVALID_REASON_FOR_MORTGAGE,
            "remortgage_reason": obj.get("remortgage_reason") if obj.get("remortgage_reason") is not None else SourceDetailsReasonForRemortgage.INVALID_REASON_FOR_REMORTGAGE,
            "mortgage_type": obj.get("mortgage_type") if obj.get("mortgage_type") is not None else CdmMortgageType.INVALID_MORTGAGE_TYPE,
            "buy_to_let_expected_rental_income_per_month": obj.get("buy_to_let_expected_rental_income_per_month"),
            "buy_to_let_number_of_properties_owned_excluding_own_residence": obj.get("buy_to_let_number_of_properties_owned_excluding_own_residence"),
            "buy_to_let_total_borrowing_on_properties_excluding_own_residence": obj.get("buy_to_let_total_borrowing_on_properties_excluding_own_residence"),
            "buy_to_let_number_of_floors": obj.get("buy_to_let_number_of_floors"),
            "buy_to_let_shorthold_tenancy_agreement": obj.get("buy_to_let_shorthold_tenancy_agreement"),
            "buy_to_let_shorthold_tenancy_agreements_total_for_property": obj.get("buy_to_let_shorthold_tenancy_agreements_total_for_property"),
            "buy_to_let_number_of_tenants": obj.get("buy_to_let_number_of_tenants"),
            "buy_to_let_tenant_status": obj.get("buy_to_let_tenant_status") if obj.get("buy_to_let_tenant_status") is not None else SourceDetailsTenantStatus.INVALID_TENANT_STATUS,
            "buy_to_let_corporate_let": obj.get("buy_to_let_corporate_let"),
            "buy_to_let_house_of_multiple_occupancy": obj.get("buy_to_let_house_of_multiple_occupancy"),
            "buy_to_let_bedsit": obj.get("buy_to_let_bedsit"),
            "buy_to_let_bedsit_number_of_rooms": obj.get("buy_to_let_bedsit_number_of_rooms"),
            "buy_to_let_limited_company": obj.get("buy_to_let_limited_company"),
            "buy_to_let_limited_company_spv": obj.get("buy_to_let_limited_company_spv"),
            "buy_to_let_landlord_status": obj.get("buy_to_let_landlord_status") if obj.get("buy_to_let_landlord_status") is not None else SourceDetailsLandlordStatus.INVALID_LANDLORD_STATUS,
            "buy_to_let_refurbishment_type": obj.get("buy_to_let_refurbishment_type") if obj.get("buy_to_let_refurbishment_type") is not None else SourceDetailsBuyToLetRefurbishmentType.INVALID_BTL_REFURBISHMENT_TYPE,
            "buy_to_let_property_occupied_by_family_member": obj.get("buy_to_let_property_occupied_by_family_member"),
            "buy_to_let_consumer": obj.get("buy_to_let_consumer"),
            "buy_to_let_consumer_regulated": obj.get("buy_to_let_consumer_regulated"),
            "buy_to_let_limited_company_name": obj.get("buy_to_let_limited_company_name"),
            "buy_to_let_applicants_are_high_tax_rate_payers": obj.get("buy_to_let_applicants_are_high_tax_rate_payers"),
            "buy_to_let_allows_top_slicing": obj.get("buy_to_let_allows_top_slicing"),
            "payment_method": obj.get("payment_method") if obj.get("payment_method") is not None else SourceDetailsPaymentMethod.INVALID_PAYMENT_METHOD,
            "part_investment_loan_required_investment_part": obj.get("part_investment_loan_required_investment_part"),
            "property_postcode": obj.get("property_postcode"),
            "property_type": obj.get("property_type") if obj.get("property_type") is not None else CdmSourceDetailsPropertyType.INVALID_PROPERTY_TYPE,
            "property_tenure": obj.get("property_tenure") if obj.get("property_tenure") is not None else CdmSourceDetailsPropertyTenure.INVALID_PROPERTY_TENURE,
            "mortgage_class_fixed": obj.get("mortgage_class_fixed"),
            "mortgage_class_variable": obj.get("mortgage_class_variable"),
            "mortgage_class_capped": obj.get("mortgage_class_capped"),
            "mortgage_class_libor_linked": obj.get("mortgage_class_libor_linked"),
            "mortgage_class_discount": obj.get("mortgage_class_discount"),
            "mortgage_class_tracker": obj.get("mortgage_class_tracker"),
            "filter_cashback": obj.get("filter_cashback"),
            "filter_product_term_period_from_months": obj.get("filter_product_term_period_from_months"),
            "filter_product_term_period_to_months": obj.get("filter_product_term_period_to_months"),
            "filter_free_legal_fees": obj.get("filter_free_legal_fees"),
            "filter_free_lender_fees": obj.get("filter_free_lender_fees"),
            "filter_max_acceptable_arrangement_fee": obj.get("filter_max_acceptable_arrangement_fee"),
            "filter_max_acceptable_total_fees": obj.get("filter_max_acceptable_total_fees"),
            "filter_no_erc_payable": obj.get("filter_no_erc_payable"),
            "filter_erc_payable_after_initial_period": obj.get("filter_erc_payable_after_initial_period"),
            "filter_ccjs_acceptable": obj.get("filter_ccjs_acceptable"),
            "filter_ivas_acceptable": obj.get("filter_ivas_acceptable"),
            "filter_bankruptcy_acceptable": obj.get("filter_bankruptcy_acceptable"),
            "filter_arrears_acceptable": obj.get("filter_arrears_acceptable"),
            "filter_defaults_acceptable": obj.get("filter_defaults_acceptable"),
            "filter_dmps_acceptable": obj.get("filter_dmps_acceptable"),
            "filter_payday_loans_acceptable": obj.get("filter_payday_loans_acceptable"),
            "filter_is_offset": obj.get("filter_is_offset"),
            "filter_no_stepped": obj.get("filter_no_stepped"),
            "filter_help_to_buy": obj.get("filter_help_to_buy"),
            "filter_help_to_buy_shared_equity": obj.get("filter_help_to_buy_shared_equity"),
            "filter_valuation_fee": obj.get("filter_valuation_fee"),
            "filter_overpayments_allowed": obj.get("filter_overpayments_allowed"),
            "filter_higher_lending_charge": obj.get("filter_higher_lending_charge"),
            "filter_direct": obj.get("filter_direct"),
            "filter_included_lenders": obj.get("filter_included_lenders"),
            "filter_excluded_lenders": obj.get("filter_excluded_lenders"),
            "filter_sort_results_by_column": SourceDetailsSortColumn.from_dict(obj["filter_sort_results_by_column"]) if obj.get("filter_sort_results_by_column") is not None else None,
            "filter_guarantors": obj.get("filter_guarantors"),
            "filter_portable": obj.get("filter_portable"),
            "filter_no_arrangement_fee": obj.get("filter_no_arrangement_fee"),
            "filter_no_booking_fee": obj.get("filter_no_booking_fee"),
            "filter_refunded_valuation_fees": obj.get("filter_refunded_valuation_fees"),
            "filter_loyalty": obj.get("filter_loyalty"),
            "filter_retention": obj.get("filter_retention"),
            "filter_refunded_legal_fees": obj.get("filter_refunded_legal_fees"),
            "filter_exclusive": obj.get("filter_exclusive"),
            "applicants": [CdmSourceApplicant.from_dict(_item) for _item in obj["applicants"]] if obj.get("applicants") is not None else None,
            "true_cost_calculate_over_no_of_months": obj.get("true_cost_calculate_over_no_of_months"),
            "true_cost_disable_calculate_over_initial_period": obj.get("true_cost_disable_calculate_over_initial_period"),
            "true_cost_disable_add_fees_that_will_be_added_to_loan": obj.get("true_cost_disable_add_fees_that_will_be_added_to_loan"),
            "true_cost_disable_add_fees_payable_to_true_cost_total": obj.get("true_cost_disable_add_fees_payable_to_true_cost_total"),
            "true_cost_disable_deduct_cashback": obj.get("true_cost_disable_deduct_cashback"),
            "true_cost_disable_deduct_refunded_fees": obj.get("true_cost_disable_deduct_refunded_fees"),
            "true_cost_pay_broker_fee_up_front": obj.get("true_cost_pay_broker_fee_up_front"),
            "true_cost_pay_arrangement_fee_up_front": obj.get("true_cost_pay_arrangement_fee_up_front"),
            "number_of_items": obj.get("number_of_items"),
            "term_unit": obj.get("term_unit") if obj.get("term_unit") is not None else CdmSourceDetailsTermUnit.INVALID_TERM_UNIT,
            "search_matching_type": obj.get("search_matching_type") if obj.get("search_matching_type") is not None else SourceDetailsSearchMatchingType.INVALID_SEARCH_MATCHING_TYPE,
            "stress_test_number_of_increments": obj.get("stress_test_number_of_increments"),
            "stress_test_rate_increment_percent": obj.get("stress_test_rate_increment_percent"),
            "exclude_retention": obj.get("exclude_retention")
        })
        return _obj


