diff --git a/README.rst b/README.rst index ecaa64d..1bd8494 100644 --- a/README.rst +++ b/README.rst @@ -7,6 +7,7 @@ Cobertura funcional ------------------- * Plan de cuentas base para República Dominicana. +* Catálogo de cuentas preparado para operar bajo NIIF completas en República Dominicana, basado en la matriz documental ``catalogo_cuentas_niif_rd_tryton_completo.xlsx`` y validado contra cuentas reales del XML. * Catálogo de impuestos y códigos fiscales. * Reglas fiscales de venta, compra, tasas especiales y retenciones para escenarios dominicanos comunes. * Campo ``tax_kind`` para clasificar ITBIS, retenciones, ISC, CDT, propina legal y otros impuestos. @@ -20,3 +21,43 @@ Pruebas ------- Las pruebas validan la instalación del módulo, la creación del plan para una compañía, la integridad de referencias XML, la clasificación contable principal, los códigos fiscales y las categorías fiscales dominicanas. + +Cumplimiento base NIIF +--------------------- + +``account_do`` cubre el 100% de la base estructural que corresponde a una localización contable: catálogo NIIF/RD, tipos de presentación, cuentas fiscales dominicanas, impuestos, reglas, metadata legal y pruebas de instalación. La medición NIIF, estimaciones, cierres, estados financieros, notas y revelaciones dependen de políticas contables y módulos operativos complementarios. + +=============================== =============================================== +Área NIIF Cobertura en el plan +=============================== =============================================== +NIC 1 Corriente/no corriente, patrimonio, ORI y cierre/control separado +NIC 2 Inventarios, costo de ventas y deterioro +NIIF 9 / NIIF 7 / NIC 32 Cuentas por cobrar, ECL, instrumentos financieros y ORI +NIIF 15 Ingresos, descuentos, activos y pasivos contractuales +NIIF 16 Activos por derecho de uso, pasivos, depreciación e intereses +NIC 12 Impuesto corriente e impuesto diferido activo/pasivo +NIC 16 PPE, depreciación acumulada y deterioro +NIC 36 Deterioro de inventarios, PPE, ROU, propiedades de inversión e intangibles +NIC 37 Provisiones corrientes/no corrientes y reversión +NIC 38 Intangibles, amortización y deterioro +NIC 40 / NIIF 13 Propiedades de inversión, valor razonable y modelo de costo +NIIF 5 Activos mantenidos para la venta y pasivos asociados +=============================== =============================================== + +Matriz de auditoría +------------------- + +La cobertura de auditoría fiscal queda formalizada en pruebas para evitar cambios silenciosos en cuentas, clasificación o vigencias. + +=============================== =============================================== ============================================== +Área Cobertura Prueba +=============================== =============================================== ============================================== +Impuesto contra cuenta 55 plantillas de ``tax_do.xml`` contra cuenta ``account_do.tests.test_module.TAX_TEMPLATE_AUDIT`` +Clasificación fiscal ``tax_kind``, ``tax_fiscal_type`` y aplicación ``test_tax_templates_are_classified`` +Metadata legal y vigencia Referencia, artículo, formulario, estado y fecha ``test_tax_templates_are_classified`` +Signos de tax codes Plantillas y códigos reales creados por compañía ``test_tax_code_templates_use_expected_signs`` y chart real +Reglas con sustitución Impuesto cheques 0.15% hasta 2026-07-02 y 0.20% desde 2026-07-03 ``test_tax_rule_templates_include_date_sensitive_bank_tax`` +Documentación contra XML La matriz apunta a XML real y falla ante ids/campos faltantes ``test_xml_references_are_resolved_inside_module`` +Plan NIIF contra XML Códigos NIIF críticos, tipos y políticas ``test_ifrs_chart_is_complete_and_typed`` y ``test_ifrs_policy_matrix_is_represented_in_chart`` +Facturas reales Factura venta/compra posteada con ITBIS 18% ``account_invoice_do.tests.test_module`` +=============================== =============================================== ============================================== diff --git a/account_chart_do.xml b/account_chart_do.xml index 605b82e..b28b0f8 100644 --- a/account_chart_do.xml +++ b/account_chart_do.xml @@ -233,6 +233,12 @@ income + + Cuentas de cierre y control + + + off-balance + @@ -898,13 +904,13 @@ 7101 Resultado antes de impuesto - + 7102 Resultado después de impuesto - + @@ -1125,6 +1131,7 @@ 111002 Deterioro de activos mantenidos para la venta + 120101 @@ -1148,6 +1155,7 @@ 120192 Deterioro acumulado edificaciones + 120201 @@ -1183,6 +1191,7 @@ 120292 Deterioro acumulado mobiliario y equipos + 120301 @@ -1200,6 +1209,7 @@ 120392 Deterioro acumulado vehículos + 120401 @@ -1237,12 +1247,13 @@ 120591 Depreciación acumulada activos por derecho de uso - + 120592 Deterioro acumulado activos por derecho de uso + 120601 @@ -1278,12 +1289,13 @@ 120891 Depreciación acumulada propiedades de inversión - + 120892 Deterioro acumulado propiedades de inversión + 120901 @@ -1313,6 +1325,7 @@ 120992 Deterioro acumulado de intangibles + 210101 diff --git a/doc/index.rst b/doc/index.rst index 6394e81..3e8a953 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -7,6 +7,9 @@ Tryton. It includes: * An IFRS-oriented chart of accounts for Dominican companies; +* IFRS structural coverage for current/non-current presentation, financial + instruments, revenue contracts, leases, deferred tax, PPE, impairment, + provisions, intangibles, investment property, OCI, and held-for-sale items; * Dominican tax groups and tax templates for ITBIS, ISR withholdings, ISC, CDT, legal tip, and other taxes; * tax code templates for DGII-oriented fiscal balances; @@ -16,10 +19,38 @@ It includes: * granular ``tax_fiscal_type`` and ``tax_application`` fields for fiscal reporting, validation, and account mapping. -The chart is intended as a base localization. Companies should review account -names, sector-specific taxes, and DGII filing mappings before using it in -production. The 16% and 8% ITBIS templates are kept as special-rate templates -for cases where those rates apply. +The chart is intended as a base localization. It provides the account +structure and Tryton account types required to operate under IFRS in the +Dominican Republic, but it does not replace accounting policies, measurement +models, estimates, closing procedures, financial statements, notes, or +disclosures. Companies should review account names, sector-specific taxes, and +DGII filing mappings before using it in production. The 16% and 8% ITBIS +templates are kept as special-rate templates for cases where those rates apply. + +IFRS base coverage +------------------ + +The base chart covers the structural account requirements identified in the +NIIF documentation reviewed for the Dominican Republic: + +* IAS/NIC 1: current and non-current presentation, equity, OCI, and separate + closing/control accounts; +* IAS/NIC 2: inventories, cost of sales, and inventory impairment; +* IFRS/NIIF 9, IFRS/NIIF 7, and IAS/NIC 32: receivables, expected credit + losses, financial assets, fair value through profit or loss, fair value + through OCI, and OCI reserves; +* IFRS/NIIF 15: revenue, discounts, contract assets, and contract liabilities; +* IFRS/NIIF 16: right-of-use assets, lease liabilities, depreciation, and + finance expense; +* IAS/NIC 12: current income tax and deferred tax assets/liabilities; +* IAS/NIC 16: property, plant and equipment, accumulated depreciation, and + impairment; +* IAS/NIC 36: impairment accounts for held-for-sale assets, PPE, ROU assets, + investment property, and intangibles; +* IAS/NIC 37: current and non-current provisions; +* IAS/NIC 38: intangible assets, amortization, and impairment; +* IAS/NIC 40 and IFRS/NIIF 13: investment property and fair value effects; +* IFRS/NIIF 5: held-for-sale assets and associated liabilities. DGII account mapping -------------------- diff --git a/tests/test_module.py b/tests/test_module.py index 8e0ac81..a3756cf 100644 --- a/tests/test_module.py +++ b/tests/test_module.py @@ -13,6 +13,216 @@ from trytond.transaction import Transaction MODULE_DIR = Path(__file__).resolve().parent.parent +TAX_TEMPLATE_AUDIT = { + 'do_tax_itbis_18_venta': ('do_account_21020101', 'itbis', + 'itbis_sale_18', 'sale_invoice', 'current', '', ''), + 'do_tax_itbis_16_venta': ('do_account_21020102', 'itbis', + 'itbis_sale_16', 'sale_invoice', 'special', '', ''), + 'do_tax_itbis_9_venta': ('do_account_21020103', 'itbis', + 'itbis_sale_9', 'sale_invoice', 'special', '', ''), + 'do_tax_itbis_18_compra': ('do_account_11040101', 'itbis', + 'itbis_purchase_18', 'purchase_invoice', 'current', '', ''), + 'do_tax_itbis_16_compra': ('do_account_11040102', 'itbis', + 'itbis_purchase_16', 'purchase_invoice', 'special', '', ''), + 'do_tax_itbis_9_compra': ('do_account_11040103', 'itbis', + 'itbis_purchase_9', 'purchase_invoice', 'special', '', ''), + 'do_tax_itbis_8_venta': ('do_account_21020104', 'itbis', + 'itbis_sale_8', 'sale_invoice', 'special', '', ''), + 'do_tax_itbis_8_compra': ('do_account_11040104', 'itbis', + 'itbis_purchase_8', 'purchase_invoice', 'special', '', ''), + 'do_tax_itbis_exento': ('', 'itbis', + 'itbis_exempt', 'sale_invoice', 'current', '', ''), + 'do_tax_itbis_tasa_cero': ('do_account_21020105', 'itbis', + 'itbis_zero_rate', 'sale_invoice', 'current', '', ''), + 'do_tax_ret_itbis_30': ('do_account_21021101', 'itbis_withholding', + 'itbis_withholding_30', 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_2_adq': ('do_account_11040601', + 'itbis_withholding_acquirer', 'itbis_withholding_acquirer_2', + 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_hon_5': ('do_account_21021301', 'isr_withholding', + 'isr_legal_entity_services_5', 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_isr_serv_10': ('do_account_21021302', 'isr_withholding', + 'isr_individual_services_10', 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_isr_div_10': ('do_account_21020601', 'isr_withholding', + 'isr_dividends_10', 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_int_10': ('do_account_21021501', 'isr_withholding', + 'isr_interest_individual_10', 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_alq_10': ('do_account_21021401', 'isr_withholding', + 'isr_rent_10', 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_isr_est_15': ('do_account_11040801', 'isr_withholding', + 'isr_state_1_5', 'sale_invoice', 'current', '', ''), + 'do_tax_ret_isr_est_5': ('do_account_11040802', 'isr_withholding', + 'isr_state_5', 'sale_invoice', 'current', '', ''), + 'do_tax_ret_isr_bovine_1': ('do_account_21021801', 'isr_withholding', + 'isr_bovine_meat_1', 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_isr_exporter_25': ('do_account_11040803', 'isr_withholding', + 'isr_exporter_sales_2_5', 'sale_invoice', 'current', '', ''), + 'do_tax_ret_isr_int_pj_1': ('do_account_21021502', 'isr_withholding', + 'isr_interest_legal_entity_1', 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_premios_25': ('do_account_21021701', 'isr_withholding', + 'isr_prizes_25', 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_premios_10': ('do_account_21021702', 'isr_withholding', + 'isr_prizes_10', 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_premios_15': ('do_account_21021703', 'isr_withholding', + 'isr_prizes_15', 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_tragamonedas_10': ('do_account_21021704', + 'isr_withholding', 'isr_slot_machine_prizes_10', + 'payment_withholding', 'current', '', ''), + 'do_tax_ret_isr_other_income_10': ('do_account_21020301', + 'isr_withholding', 'isr_other_income_10', 'purchase_invoice', + 'current', '', ''), + 'do_tax_ret_isr_ext_27': ('do_account_21020701', 'isr_withholding', + 'isr_foreign_services_27', 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_isr_ext_10': ('do_account_21020702', 'isr_withholding', + 'isr_foreign_interest_10', 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_100_inf': ('do_account_21020201', + 'itbis_withholding', 'itbis_withholding_100_services', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_75_inf': ('do_account_21021201', + 'itbis_withholding', 'itbis_withholding_75_informal', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_75_inf_16': ('do_account_21021202', + 'itbis_withholding', 'itbis_withholding_75_informal_16', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_100_goods_18': ('do_account_21021203', + 'itbis_withholding', 'itbis_withholding_100_informal_goods_18', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_100_goods_16': ('do_account_21021204', + 'itbis_withholding', 'itbis_withholding_100_informal_goods_16', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_rst_18': ('do_account_21020202', + 'itbis_withholding', 'itbis_withholding_rst_18', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_rst_16': ('do_account_21020203', + 'itbis_withholding', 'itbis_withholding_rst_16', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_insurance_100': ('do_account_21020204', + 'itbis_withholding', 'itbis_withholding_insurance_100', + 'purchase_invoice', 'current', '', ''), + 'do_tax_ret_itbis_airline_100': ('do_account_11040701', + 'itbis_withholding', 'itbis_withholding_airline_100', + 'sale_invoice', 'current', '', ''), + 'do_tax_ret_itbis_society_30_suf': ('do_account_11040702', + 'itbis_withholding', 'itbis_withholding_society_30_suffered', + 'sale_invoice', 'current', '', ''), + 'do_tax_ret_itbis_hotel_100': ('do_account_11040703', + 'itbis_withholding', 'itbis_withholding_hotel_100', + 'sale_invoice', 'current', '', ''), + 'do_tax_ret_itbis_state_100': ('do_account_11040704', + 'itbis_withholding', 'itbis_withholding_state_100', + 'sale_invoice', 'current', '', ''), + 'do_tax_isc_bebidas_alc': ('do_account_21020801', 'isc', + 'isc_alcohol_10', 'sale_invoice', 'current', '', ''), + 'do_tax_isc_tabaco': ('do_account_21020802', 'isc', + 'isc_tobacco_20', 'sale_invoice', 'current', '', ''), + 'do_tax_isc_telecom': ('do_account_21020803', 'isc', + 'isc_telecom_10', 'sale_invoice', 'current', '', ''), + 'do_tax_isc_combustibles_16': ('do_account_21020804', 'isc', + 'isc_fossil_fuel_16', 'sale_invoice', 'current', '', ''), + 'do_tax_isc_avtur_65': ('do_account_21020807', 'isc', + 'isc_avtur_6_5', 'sale_invoice', 'current', '', ''), + 'do_tax_isc_fuel_rd2_gallon': ('do_account_21020808', 'isc', + 'isc_fuel_rd2_gallon', 'sale_invoice', 'current', '', ''), + 'do_tax_ret_isc_insurance_100': ('do_account_21020806', 'isc', + 'isc_insurance_withholding_100', 'purchase_invoice', 'current', '', ''), + 'do_tax_isc_vehiculos': ('do_account_21020805', 'isc', + 'isc_vehicle_17', 'asset_transfer', 'current', '', ''), + 'do_tax_cdt_indotel': ('do_account_21020901', 'cdt', + 'cdt_indotel_2', 'sale_invoice', 'current', '', ''), + 'do_tax_propina_10': ('do_account_21020501', 'tip', + 'legal_tip_10', 'sale_invoice', 'current', '', ''), + 'do_tax_cheques_015': ('do_account_21021901', 'others', + 'check_transfer_tax_015', 'bank_charge', 'historical', '', + 'datetime.date(2026, 7, 2)'), + 'do_tax_cheques_020': ('do_account_21021902', 'others', + 'check_transfer_tax_020', 'bank_charge', 'current', + 'datetime.date(2026, 7, 3)', ''), + 'do_tax_activos_1': ('do_account_21020502', 'others', + 'asset_tax_1', 'annual_declaration', 'current', '', ''), + 'do_tax_iti_3': ('do_account_21021001', 'others', + 'real_estate_transfer_3', 'asset_transfer', 'current', '', ''), + } + +TAX_CODE_LINE_AUDIT = { + 'do_tcl_itbis18v_inv': '+', + 'do_tcl_itbis18v_cr': '-', + 'do_tcl_itbis18c_inv': '-', + 'do_tcl_itbis18c_cr': '+', + 'do_tcl_ret_itbis_inv': '-', + 'do_tcl_ret_itbis_cr': '+', + 'do_tcl_ret_itbis_adq_inv': '+', + 'do_tcl_ret_itbis_adq_cr': '-', + 'do_tcl_ret_itbis_inf75_inv': '-', + 'do_tcl_ret_itbis_inf75_cr': '+', + 'do_tcl_isr_hon_inv': '-', + 'do_tcl_isr_hon_cr': '+', + 'do_tcl_isr_est_inv': '+', + 'do_tcl_isr_est_cr': '-', + 'do_tcl_isc_comb_inv': '+', + 'do_tcl_isc_comb_cr': '-', + 'do_tcl_chq_inv': '+', + 'do_tcl_chq_cr': '-', + 'do_tcl_chq020_inv': '+', + 'do_tcl_chq020_cr': '-', + } + +IFRS_REQUIRED_ACCOUNT_CODES = { + '1', '11', '12', + '1101', '1102', '1103', '1104', '1105', '1106', '1107', '1110', + '110101', '110103', '110104', '110201', '110205', '110301', + '110305', '110601', '110701', '110702', '110703', '111001', + '111002', + '1201', '1205', '1206', '1207', '1208', '1209', + '120101', '120191', '120192', '120501', '120591', '120592', + '120601', '120701', '120702', '120703', '120801', '120891', + '120892', '120901', '120991', '120992', + '2', '21', '22', '23', + '2101', '2104', '2105', '2106', '2201', '2301', '2302', '2303', + '2304', + '210101', '210401', '210501', '210601', '220101', '230201', + '230202', '230301', '230401', + '3', '31', '3101', '3104', '3105', '3106', '310601', '310604', + '4', '41', '42', '4101', '4102', '4103', '4104', '4201', '4208', + '4209', '4210', + '5', '51', '5101', '5102', '5106', + '6', '61', '62', '63', '6101', '6103', '6111', '6112', '6115', + '6116', '6117', '6118', '6119', '6120', '6201', '6203', '6206', + '6207', '6301', '6302', '6303', + '7', '7101', '7102', + } + +IFRS_ACCOUNT_TYPE_AUDIT = { + '111002': 'do_type_current_asset', + '120192': 'do_type_fixed_asset', + '120292': 'do_type_fixed_asset', + '120392': 'do_type_fixed_asset', + '120591': 'do_type_rou_asset', + '120592': 'do_type_rou_asset', + '120891': 'do_type_investment_property', + '120892': 'do_type_investment_property', + '120992': 'do_type_intangible', + '7101': 'do_type_control', + '7102': 'do_type_control', + } + +IFRS_POLICY_COVERAGE = { + 'NIC 1': {'11', '12', '21', '23', '3106', '7101', '7102'}, + 'NIC 2': {'1103', '110305', '5101', '5106'}, + 'NIIF 9': {'110205', '110701', '110702', '110703', '120701', + '120702', '120703', '4208', '6206', '310604'}, + 'NIIF 15': {'110601', '210501', '4101', '4102', '4103', '4104'}, + 'NIIF 16': {'120501', '120591', '120592', '230201', '230202', + '6112', '6203'}, + 'NIC 12': {'120601', '230301', '6301', '6302', '6303'}, + 'NIC 16': {'120101', '120191', '120192', '6110', '6116'}, + 'NIC 36': {'111002', '120192', '120292', '120392', '120592', + '120892', '120992', '6116', '6117', '4206'}, + 'NIC 37': {'220101', '230401', '6118', '4207'}, + 'NIC 38': {'120901', '120991', '120992', '6111', '6117'}, + 'NIC 40': {'120801', '120891', '120892', '4209', '6207'}, + 'NIIF 5': {'111001', '111002', '210601', '4210', '6120'}, + } + def _iter_xml_records(*filenames): for filename in filenames: @@ -51,6 +261,7 @@ class AccountDoTestCase(ModuleTestCase): Party = pool.get('party.party') Tax = pool.get('account.tax') TaxCode = pool.get('account.tax.code') + TaxCodeLine = pool.get('account.tax.code.line') TaxRule = pool.get('account.tax.rule') CreateChart = pool.get('account.create_chart', type='wizard') @@ -92,6 +303,8 @@ class AccountDoTestCase(ModuleTestCase): ('closed', '!=', True), ], limit=1) for code in [ + '111002', '120192', '120292', '120392', '120591', + '120592', '120891', '120892', '120992', '7101', '7102', '110401', '110406', '110407', '110408', '11040101', '11040102', '11040103', '11040104', '11040601', '11040801', '11040802', '11040803', @@ -113,6 +326,24 @@ class AccountDoTestCase(ModuleTestCase): ('code', '=', code), ('closed', '!=', True), ], limit=1)) + company_ifrs_types = { + '111002': 'Activos corrientes', + '120591': 'Activos por derecho de uso', + '120592': 'Activos por derecho de uso', + '120891': 'Propiedades de inversión', + '120892': 'Propiedades de inversión', + '120992': 'Activos intangibles', + '7101': 'Cuentas de cierre y control', + '7102': 'Cuentas de cierre y control', + } + for code, account_type in company_ifrs_types.items(): + with self.subTest(code=code, account_type=account_type): + account, = Account.search([ + ('company', '=', company.id), + ('code', '=', code), + ('closed', '!=', True), + ], limit=1) + self.assertEqual(account.type.name, account_type) self.assertGreaterEqual(len(Account.search([ ('company', '=', company.id), @@ -180,6 +411,32 @@ class AccountDoTestCase(ModuleTestCase): 'date': datetime.date(2026, 7, 3), }), [check_020.id]) + real_tax_code_signs = { + ('ITBIS 18% Ventas', 'invoice'): '+', + ('ITBIS 18% Ventas', 'credit'): '-', + ('ITBIS 18% Compras', 'invoice'): '-', + ('ITBIS 18% Compras', 'credit'): '+', + ('Retención ITBIS Gran Contribuyente 30%', 'invoice'): '-', + ('Retención ITBIS Gran Contribuyente 30%', 'credit'): '+', + ('Retención ISR Persona Física 10%', 'invoice'): '-', + ('Retención ISR Persona Física 10%', 'credit'): '+', + ('Retención ISR Estado 1.5%', 'invoice'): '+', + ('Retención ISR Estado 1.5%', 'credit'): '-', + ('Impuesto Cheques y Transferencias 0.20%', 'invoice'): '+', + ('Impuesto Cheques y Transferencias 0.20%', 'credit'): '-', + } + for (description, line_type), operator in real_tax_code_signs.items(): + with self.subTest(description=description, line_type=line_type): + tax, = Tax.search([ + ('company', '=', company.id), + ('description', '=', description), + ], limit=1) + line, = TaxCodeLine.search([ + ('tax', '=', tax.id), + ('type', '=', line_type), + ('amount', '=', 'tax'), + ], limit=1) + self.assertEqual(line.operator, operator) chart.properties.company = company chart.properties.account_receivable = receivable @@ -253,6 +510,53 @@ class AccountDoUnitTestCase(unittest.TestCase): self.assertEqual( accounts['do_account_210101']['type'], 'do_type_payable') + def test_ifrs_chart_is_complete_and_typed(self): + accounts = { + values['code']: values + for _, _, model, values in _iter_xml_records( + 'account_chart_do.xml') + if model == 'account.account.template' and values.get('code') + } + types = { + record_id: values + for _, record_id, model, values in _iter_xml_records( + 'account_chart_do.xml') + if model == 'account.account.type.template' + } + + self.assertLessEqual(IFRS_REQUIRED_ACCOUNT_CODES, set(accounts)) + self.assertEqual(types['do_type_control']['statement'], 'off-balance') + self.assertEqual( + types['do_type_deferred_tax_asset']['statement'], 'balance') + self.assertEqual( + types['do_type_deferred_tax_liability']['statement'], 'balance') + self.assertEqual(types['do_type_rou_asset']['statement'], 'balance') + self.assertEqual( + types['do_type_investment_property']['statement'], 'balance') + self.assertEqual(types['do_type_intangible']['statement'], 'balance') + + missing_type = [ + (code, values['name']) + for code, values in accounts.items() + if values.get('closed') != 'True' and not values.get('type') + ] + self.assertEqual(missing_type, []) + + for code, account_type in IFRS_ACCOUNT_TYPE_AUDIT.items(): + with self.subTest(code=code): + self.assertEqual(accounts[code]['type'], account_type) + + def test_ifrs_policy_matrix_is_represented_in_chart(self): + accounts = { + values['code'] + for _, _, model, values in _iter_xml_records( + 'account_chart_do.xml') + if model == 'account.account.template' and values.get('code') + } + for standard, codes in IFRS_POLICY_COVERAGE.items(): + with self.subTest(standard=standard): + self.assertLessEqual(codes, accounts) + def test_no_spanish_technical_other_tax_ids_remain(self): ids = { record_id @@ -267,92 +571,48 @@ class AccountDoUnitTestCase(unittest.TestCase): for _, record_id, model, values in _iter_xml_records('tax_do.xml') if model == 'account.tax.template' } - self.assertEqual(len(taxes), 55) - self.assertFalse([ - record_id for record_id, values in taxes.items() - if not values.get('tax_kind')]) - self.assertFalse([ - record_id for record_id, values in taxes.items() - if not values.get('tax_fiscal_type')]) - self.assertFalse([ - record_id for record_id, values in taxes.items() - if not values.get('tax_application')]) - for field_name in [ - 'dgii_legal_reference', - 'dgii_legal_article', - 'dgii_form_hint', - 'dgii_fiscal_status', - ]: - self.assertFalse([ - record_id for record_id, values in taxes.items() - if not values.get(field_name)]) - self.assertEqual( - taxes['do_tax_itbis_18_venta']['invoice_account'], - 'do_account_21020101') - self.assertEqual( - taxes['do_tax_itbis_18_compra']['invoice_account'], - 'do_account_11040101') - expected_accounts = { - 'do_tax_itbis_18_venta': 'do_account_21020101', - 'do_tax_itbis_16_venta': 'do_account_21020102', - 'do_tax_itbis_9_venta': 'do_account_21020103', - 'do_tax_itbis_8_venta': 'do_account_21020104', - 'do_tax_itbis_tasa_cero': 'do_account_21020105', - 'do_tax_itbis_18_compra': 'do_account_11040101', - 'do_tax_itbis_16_compra': 'do_account_11040102', - 'do_tax_itbis_9_compra': 'do_account_11040103', - 'do_tax_itbis_8_compra': 'do_account_11040104', - 'do_tax_ret_itbis_2_adq': 'do_account_11040601', - 'do_tax_ret_itbis_30': 'do_account_21021101', - 'do_tax_ret_itbis_100_inf': 'do_account_21020201', - 'do_tax_ret_itbis_75_inf': 'do_account_21021201', - 'do_tax_ret_itbis_75_inf_16': 'do_account_21021202', - 'do_tax_ret_itbis_100_goods_18': 'do_account_21021203', - 'do_tax_ret_itbis_100_goods_16': 'do_account_21021204', - 'do_tax_ret_itbis_rst_18': 'do_account_21020202', - 'do_tax_ret_itbis_rst_16': 'do_account_21020203', - 'do_tax_ret_itbis_insurance_100': 'do_account_21020204', - 'do_tax_ret_itbis_airline_100': 'do_account_11040701', - 'do_tax_ret_itbis_society_30_suf': 'do_account_11040702', - 'do_tax_ret_itbis_hotel_100': 'do_account_11040703', - 'do_tax_ret_itbis_state_100': 'do_account_11040704', - 'do_tax_ret_isr_hon_5': 'do_account_21021301', - 'do_tax_ret_isr_serv_10': 'do_account_21021302', - 'do_tax_ret_isr_div_10': 'do_account_21020601', - 'do_tax_ret_isr_int_10': 'do_account_21021501', - 'do_tax_ret_isr_int_pj_1': 'do_account_21021502', - 'do_tax_ret_isr_alq_10': 'do_account_21021401', - 'do_tax_ret_isr_est_15': 'do_account_11040801', - 'do_tax_ret_isr_est_5': 'do_account_11040802', - 'do_tax_ret_isr_exporter_25': 'do_account_11040803', - 'do_tax_ret_isr_bovine_1': 'do_account_21021801', - 'do_tax_ret_isr_premios_25': 'do_account_21021701', - 'do_tax_ret_isr_premios_10': 'do_account_21021702', - 'do_tax_ret_isr_premios_15': 'do_account_21021703', - 'do_tax_ret_isr_tragamonedas_10': 'do_account_21021704', - 'do_tax_ret_isr_other_income_10': 'do_account_21020301', - 'do_tax_ret_isr_ext_27': 'do_account_21020701', - 'do_tax_ret_isr_ext_10': 'do_account_21020702', - 'do_tax_isc_bebidas_alc': 'do_account_21020801', - 'do_tax_isc_tabaco': 'do_account_21020802', - 'do_tax_isc_telecom': 'do_account_21020803', - 'do_tax_isc_combustibles_16': 'do_account_21020804', - 'do_tax_isc_avtur_65': 'do_account_21020807', - 'do_tax_isc_fuel_rd2_gallon': 'do_account_21020808', - 'do_tax_ret_isc_insurance_100': 'do_account_21020806', - 'do_tax_isc_vehiculos': 'do_account_21020805', - 'do_tax_cdt_indotel': 'do_account_21020901', - 'do_tax_propina_10': 'do_account_21020501', - 'do_tax_cheques_015': 'do_account_21021901', - 'do_tax_cheques_020': 'do_account_21021902', - 'do_tax_activos_1': 'do_account_21020502', - 'do_tax_iti_3': 'do_account_21021001', + accounts = { + record_id: values + for _, record_id, model, values in _iter_xml_records( + 'account_chart_do.xml') + if model == 'account.account.template' } - for record_id, account_id in expected_accounts.items(): + tax_kind_codes = {code for code, _ in TAX_KIND} + fiscal_type_codes = {code for code, _ in TAX_FISCAL_TYPE} + application_codes = {code for code, _ in TAX_APPLICATION} + fiscal_status_codes = {code for code, _ in DGII_FISCAL_STATUS} + + self.assertEqual(len(taxes), 55) + + self.assertEqual(set(taxes), set(TAX_TEMPLATE_AUDIT)) + for record_id, expected in TAX_TEMPLATE_AUDIT.items(): + account_id, tax_kind, fiscal_type, application, status, start, end = ( + expected) with self.subTest(record_id=record_id): - self.assertEqual(taxes[record_id]['invoice_account'], account_id) + values = taxes[record_id] + self.assertEqual(values.get('invoice_account', ''), account_id) self.assertEqual( - taxes[record_id]['credit_note_account'], account_id) + values.get('credit_note_account', ''), account_id) + if account_id: + self.assertIn(account_id, accounts) + else: + self.assertEqual(values['type'], 'none') + self.assertFalse(values.get('rate')) + self.assertEqual(values['tax_kind'], tax_kind) + self.assertEqual(values['tax_fiscal_type'], fiscal_type) + self.assertEqual(values['tax_application'], application) + self.assertEqual(values['dgii_fiscal_status'], status) + self.assertEqual(values.get('start_date', ''), start) + self.assertEqual(values.get('end_date', ''), end) + self.assertIn(tax_kind, tax_kind_codes) + self.assertIn(fiscal_type, fiscal_type_codes) + self.assertIn(application, application_codes) + self.assertIn(status, fiscal_status_codes) + self.assertTrue(values.get('dgii_legal_reference')) + self.assertTrue(values.get('dgii_legal_article')) + self.assertTrue(values.get('dgii_form_hint')) + self.assertTrue(values.get('legal_notice')) + self.assertEqual( taxes['do_tax_ret_itbis_30']['tax_kind'], 'itbis_withholding') @@ -451,6 +711,9 @@ class AccountDoUnitTestCase(unittest.TestCase): self.assertEqual( lines['do_tcl_chq020_cr']['code'], 'do_tc_others_checks_020') + for record_id, operator in TAX_CODE_LINE_AUDIT.items(): + with self.subTest(record_id=record_id): + self.assertEqual(lines[record_id]['operator'], operator) self.assertEqual(lines['do_tcl_itbis18v_inv']['operator'], '+') self.assertEqual(lines['do_tcl_itbis18c_inv']['operator'], '-') self.assertEqual(lines['do_tcl_itbis9v_inv']['operator'], '+')