"""Factories for testing models.""" import datetime from decimal import Decimal import factory from abacus_common_logic.test_utils.factories import ( BaseModelFactory, BaseModelFactoryWithTimestamps, ) from abacus_contract.constants import constants from abacus_contract.models.account_contract import AccountContract from abacus_contract.models.contract import Contract from abacus_contract.models.contract_advance import ContractAdvance from abacus_contract.models.contract_exclusion import ContractExclusion from abacus_contract.models.contract_flowthrough import ContractFlowthrough from abacus_contract.models.contract_lifecycle import ContractLifecycle from abacus_contract.models.contract_lifecycle_schedule import ContractLifecycleSchedule from abacus_contract.models.contract_lifecycle_schedule_detail import ( ContractLifecycleScheduleDetail, ) from abacus_contract.models.contract_mechanical_deduction import ( ContractMechanicalDeduction, ) from abacus_contract.models.contract_party import ContractParty from abacus_contract.models.contract_reserve import ContractReserve from abacus_contract.models.contract_template import ContractTemplate from abacus_contract.models.contract_term import ContractTerm from abacus_contract.models.contract_term_condition import ContractTermCondition from abacus_contract.models.contract_term_schedule import ContractTermSchedule from abacus_contract.models.historical_contract_advance import ( HistoricalContractAdvance, ) from abacus_contract.models.legacy_contract import LegacyContract from abacus_contract.models.reference_flowthrough_calculation import ( ReferenceFlowthroughCalculation, ) from abacus_contract.models.reference_mechanical_rate import ReferenceMechanicalRate from abacus_contract.models.reference_payment_entity import ReferencePaymentEntity from abacus_contract.models.reference_payment_type import ReferencePaymentType from abacus_contract.models.reference_sap_profit_center import ReferenceSapProfitCenter from abacus_contract.models.reference_signing_entity import ReferenceSigningEntity from abacus_contract.models.reference_transaction_type import ReferenceTransactionType from abacus_contract.models.reference_transaction_type_group import ( ReferenceTransactionTypeGroup, ) from abacus_contract.models.reference_transaction_type_group_transaction_type import ( ReferenceTransactionTypeGroupTransactionType, ) from abacus_contract.models.signing_entity_sap_profit_center import ( SigningEntitySapProfitCenter, ) class ReferencePaymentEntityFactory(BaseModelFactoryWithTimestamps): """Factory to create reference_payment_entity models for testing.""" class Meta: """Meta definition for the factory.""" model = ReferencePaymentEntity payment_entity_name = 'AWAL-UK' country_of_tax_reporting = 'UK' class ReferenceSapProfitCenterFactory(BaseModelFactoryWithTimestamps): """Factory to create reference_sap_profit_center models for testing.""" class Meta: """Meta definition for the factory.""" model = ReferenceSapProfitCenter profit_center = factory.Sequence(lambda n: f'UK{4914 + n}') company_code = '4912' business_group = 'ORC' display_name = factory.LazyAttribute(lambda o: f'PC {o.profit_center}') class ReferenceSigningEntityFactory(BaseModelFactory): """Factory to create reference_signing_entity models for testing.""" class Meta: """Meta definition for the factory.""" model = ReferenceSigningEntity reference_payment_entity = factory.SubFactory(ReferencePaymentEntityFactory) reference_sap_profit_center = factory.SubFactory(ReferenceSapProfitCenterFactory) company_code = factory.Sequence(lambda n: str(n).zfill(4)) legal_name = 'AWAL Digital Limited' vat_number = 'GB 423 4787 86' company_registration_number = '04430703' address = '2 Canal Reach, London, N1C 4DB' @factory.post_generation def with_junction_row(obj, create, extracted, **kwargs): """Mirror production invariant: every active SE has a junction entry for its legacy PC. Tests can opt out by passing `with_junction_row=False` to the factory call. Uses the junction factory's captured SQLAlchemy session (not ``db.session`` or ``Model.query``) so this still works under tests that patch ``db.session`` — factory-boy resolves the session at class-definition time, while ``BaseModel.create`` and ``Model.query`` resolve it at call time and would be intercepted by the mock. """ if not create or extracted is False: return session = SigningEntitySapProfitCenterFactory._meta.sqlalchemy_session existing = ( session.query(SigningEntitySapProfitCenter) .filter_by( reference_signing_entity_id=obj.reference_signing_entity_id, reference_sap_profit_center_id=obj.reference_sap_profit_center_id, deleted_at=None, ) .first() ) if existing is None: SigningEntitySapProfitCenterFactory.create( reference_signing_entity=obj, reference_sap_profit_center=obj.reference_sap_profit_center, ) class SigningEntitySapProfitCenterFactory(BaseModelFactory): """Factory for SE↔PC junction rows.""" class Meta: """Meta definition for the factory.""" model = SigningEntitySapProfitCenter reference_signing_entity = factory.SubFactory(ReferenceSigningEntityFactory) reference_sap_profit_center = factory.SubFactory(ReferenceSapProfitCenterFactory) class ContractFactory(BaseModelFactoryWithTimestamps): """Factory to create contract models for testing.""" class Meta: """Meta definition for the factory.""" model = Contract contract_name = factory.Sequence(lambda n: f'Contract {n}') term_start = datetime.date(2019, 6, 1) term_end = datetime.date(2029, 6, 1) contract_type = constants.CONTRACT_TYPES.DISTRIBUTION reference_signing_entity = factory.SubFactory(ReferenceSigningEntityFactory) reference_sap_profit_center_id = factory.LazyAttribute( lambda o: o.reference_signing_entity.reference_sap_profit_center_id ) summary_note = 'This is for the test' general_note = 'This is for the test (general_note)' is_excluded_from_accounting_run = 0 is_paythrough_contract = 0 is_primary_contract = 0 initial_start_date = datetime.date(2018, 7, 28) execution_date = None class ContractExclusionFactory(BaseModelFactory): """Factory to create contract_exclusion model for testing.""" class Meta: """Meta definition for the factory.""" model = ContractExclusion contract = factory.SubFactory(ContractFactory) exclusions = {'countries': ['USA', 'RUS'], 'stores': ['Spotify']} class ContractLifecycleScheduleDetailFactory(BaseModelFactory): """Factory to create contract_lifecycle_schedule_detail models for testing.""" class Meta: """Meta definition for the factory.""" model = ContractLifecycleScheduleDetail period_interval = 1 period_type = constants.CONTRACT_LIFECYCLE_SCHEDULE_DETAIL_PERIOD_TYPES.DAY class ContractLifecycleScheduleFactory(BaseModelFactory): """Factory to create contract lifecycle schedule model for testing.""" class Meta: """Meta definition for the factory.""" model = ContractLifecycleSchedule contract = factory.SubFactory(ContractFactory) termination_notice_detail = factory.SubFactory( ContractLifecycleScheduleDetailFactory ) renewal_offset_detail = None collection_period_detail = None renewal_type = ( constants.CONTRACT_LIFECYCLE_SCHEDULE_RENEWAL_TYPES.CONTINUOUSLY_ACTIVE ) schedule_end = None class ContractLifecycleFactory(BaseModelFactory): """Factory to create contract lifecycle model for testing.""" class Meta: """Meta definition for the factory.""" model = ContractLifecycle contract = factory.SubFactory(ContractFactory) contract_lifecycle_schedule = factory.SubFactory(ContractLifecycleScheduleFactory) last_renewed = None lifecycle_status = constants.CONTRACT_LIFECYCLE_STATUSES.INIT lifecycle_term_start = datetime.date(2025, 1, 1) lifecycle_term_end = None renewal_effective = None termination_notice_deadline = None termination_notice_received = None termination_effective = None collection_start = None collection_end = None class ContractPartyFactory(BaseModelFactoryWithTimestamps): """Factory to create contract_party models for testing.""" class Meta: """Meta definition for the factory.""" model = ContractParty contract = factory.SubFactory(ContractFactory) target_id = '1ec7c1bf-2318-4052-9406-a3e35a620bd3' target_type = 'contributor' class ContractTermFactory(BaseModelFactoryWithTimestamps): """Factory to create contract term models for testing.""" class Meta: """Meta definition for the factory.""" model = ContractTerm contract = factory.SubFactory(ContractFactory) contract_term_name = 'Test contract term' term_type = constants.CONTRACT_TERM_TYPES.LABEL attachments = ['7126'] attachments_relations = {'label_ids': ['1', '2'], 'upcs': ['3']} is_base_term = False class ContractTermConditionFactory(BaseModelFactoryWithTimestamps): """Factory to create contract term condition models for testing.""" class Meta: """Meta definition for the factory.""" model = ContractTermCondition contract_term = factory.SubFactory(ContractTermFactory) priority = 1 term_rate = 75.50 commission = 24.50 conditions = {'countries': ['USA'], 'stores': [], 'transaction_types': []} contract_term_condition_name = 'test condition name' class ContractTermScheduleFactory(BaseModelFactoryWithTimestamps): """Factory to create contract term schedule models for testing.""" class Meta: """Meta definition for the factory.""" model = ContractTermSchedule contract_term = factory.SubFactory(ContractTermFactory) schedule_id = 1 class LegacyContractFactory(BaseModelFactory): """Factory to create legacy_contract models for testing.""" class Meta: """Meta definition for the factory.""" model = LegacyContract contract = factory.SubFactory(ContractFactory) oa_contract_id = 1020 class ContractTemplateFactory(BaseModelFactoryWithTimestamps): """Factory to create contract template instances for testing.""" class Meta: """Meta definition for the factory.""" model = ContractTemplate template_name = 'GDA Template 1' run_controller_id = 1 term_duration_year = 1 contract_type = constants.CONTRACT_TYPES.DISTRIBUTION contract_terms = [ { 'attachments': ['1234'], 'conditions': [ { 'name': 'Contract Term Condition Name', 'stores': [], 'priority': 1, 'countries': [], 'term_rate': '80.00', 'transaction_types': [], } ], 'term_type': 'label', } ] contract_exclusions = {'countries': [], 'stores': []} reference_signing_entity = factory.SubFactory(ReferenceSigningEntityFactory) reference_sap_profit_center = factory.SubFactory(ReferenceSapProfitCenterFactory) class AccountContractFactory(BaseModelFactory): """Factory to create account_contract models for testing.""" class Meta: """Meta definition for the factory.""" model = AccountContract account_id = 1 contract = factory.SubFactory(ContractFactory) class ContractReserveFactory(BaseModelFactory): """Factory to create contract_reserve models for testing.""" class Meta: """Meta definition for the factory.""" model = ContractReserve contract = factory.SubFactory(ContractFactory) installments_in_months = 4 reserve_rate = 80 reserve_release_offset_in_months = 2 release_schedule = [ '0.250000000000', '0.250000000000', '0.250000000000', '0.250000000000', ] class ContractAdvanceFactory(BaseModelFactory): """Factory to create contract_advance models for testing.""" class Meta: """Meta definition for the factory.""" model = ContractAdvance contract = factory.SubFactory(ContractFactory) advance_description = 'Advance Description' amount = 100.00 currency_code = 'USD' milestone = constants.MILESTONES.RECOUPMENT milestone_description = 'Milestone Description' milestone_date = '2022-09-16' advance_status = constants.ADVANCE_STATUSES.NOT_QUALIFIED note = None reference_payment_type_id = None vat_amount = Decimal('20.00') withholding_tax_amount = Decimal('-10.00') amount_after_withholding_and_vat = Decimal('110.00') us_source_income_rate = Decimal('99.000001') class ReferenceFlowthroughCalculationFactory(BaseModelFactory): """Factory to create reference_flowthrough_calculation models for testing.""" class Meta: """Meta definition for the factory.""" model = ReferenceFlowthroughCalculation flowthrough_calculation_name = 'Test Flowthrough Calculation Name' flowthrough_calculation = 'Test Flowthrough Calculation' flowthrough_calculation_example = 'Test Flowthrough Calculation Example' flowthrough_calculation_example_summary = ( 'Test Flowthrough Calculation Example Summary' ) class ReferencePaymentTypeFactory(BaseModelFactory): """Factory to create reference_payment_type models for testing.""" class Meta: """Meta definition for the factory.""" model = ReferencePaymentType payment_type = constants.PAYMENT_TYPES.ADVANCE payment_service = 'payoneer' is_internal = False notes = 'Other payment via Payoneer' class ReferenceTransactionTypeFactory(BaseModelFactory): """Factory to create reference_transaction_type models for testing.""" class Meta: """Meta definition for the factory.""" model = ReferenceTransactionType transaction_type_name = 'Triple A' transaction_type_code = 'AAA' class ReferenceTransactionTypeGroupFactory(BaseModelFactory): """Factory to create reference_transaction_type_group class instances.""" class Meta: """Meta definition for factory.""" model = ReferenceTransactionTypeGroup transaction_type_group_name = 'Transaction Type Group' class ReferenceTransactionTypeGroupTransactionTypeFactory(BaseModelFactory): """Factory to create reference_transaction_type_group_transaction_type instances.""" class Meta: """Meta definition for factory.""" model = ReferenceTransactionTypeGroupTransactionType reference_transaction_type_group = factory.SubFactory( ReferenceTransactionTypeGroupFactory ) reference_transaction_type = factory.SubFactory(ReferenceTransactionTypeFactory) reference_transaction_type_group_admin = ( constants.REFERENCE_TRANSACTION_TYPE_GROUP_ADMIN.CONTRACT_ADMIN ) class ReferenceMechanicalRateFactory(BaseModelFactory): """Factory to create reference_mechanical_rate models for testing.""" class Meta: """Meta definition for the factory.""" model = ReferenceMechanicalRate country_code = 'USA' base_rate = '0.1240' minute_rate = '0.0238' ringtone_rate = '0.2400' effective_start_date = datetime.datetime(2004, 1, 1, 0, 0) class ContractMechanicalDeductionFactory(BaseModelFactory): """Factory to create contract_mechanical_deduction model for testing.""" class Meta: """Meta definition for the factory.""" model = ContractMechanicalDeduction contract = factory.SubFactory(ContractFactory) territory = constants.MECHANICAL_DEDUCTION_TERRITORIES.USA mechanical_type = [constants.MECHANICAL_DEDUCTION_TYPES.DIGITAL] admin_type = constants.MECHANICAL_DEDUCTION_ADMIN_TYPES.BOTH admin_fee = 20.20 class ContractFlowthroughFactory(BaseModelFactory): """Factory to create contract flowthrough model for testing.""" class Meta: """Meta definition for the factory.""" model = ContractFlowthrough contract = factory.SubFactory(ContractFactory) reference_flowthrough_calculation = factory.SubFactory( ReferenceFlowthroughCalculationFactory ) flowthrough_rate = 0.51 flowthrough_status = constants.CONTRACT_FLOWTHROUGH_STATUSES.ACTIVE has_automatic_shutoff = 1 recoupment_cap = 1234231 calculation_comment = 'Comment' previous_flowthrough_status = ( constants.CONTRACT_FLOWTHROUGH_PREVIOUS_STATUSES.PAUSED ) status_last_modified_by = 'Test User' status_last_modified = datetime.datetime(2025, 2, 28, 0, 0) class HistoricalContractAdvanceFactory(BaseModelFactory): """Factory to create historical_contract_advance models for testing.""" class Meta: """Meta definition for the factory.""" model = HistoricalContractAdvance oa_advance_id = factory.Sequence(lambda n: n) oa_contract_id = factory.Sequence(lambda n: n) account_id = 1 amount = 1000.00 currency_id = 1 currency = 'USD' due_type = 'on_delivery' date_paid = datetime.date(2024, 1, 15) exchange_rate = 1.0 description = 'Test advance payment' apply_to_period_id = 1