Hatchling cannot build editable installs when project sources rewrite a prefix. Install the package normally with test extras in Gitea Actions and keep the workflow coverage test aligned with that supported install path.
1032 lines
45 KiB
Python
1032 lines
45 KiB
Python
import unittest
|
||
import datetime
|
||
from collections import Counter
|
||
from configparser import ConfigParser
|
||
from decimal import Decimal
|
||
from pathlib import Path
|
||
from xml.etree import ElementTree as ET
|
||
|
||
from trytond.modules.account_do.tax import (
|
||
DGII_FISCAL_STATUS, TAX_APPLICATION, TAX_FISCAL_TYPE, TAX_KIND)
|
||
from trytond.pool import Pool
|
||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||
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:
|
||
path = MODULE_DIR / filename
|
||
root = ET.parse(path).getroot()
|
||
for record in root.findall('.//record'):
|
||
values = {
|
||
field.get('name'): (
|
||
field.get('ref') or field.get('eval') or field.text or '')
|
||
for field in record.findall('field')
|
||
}
|
||
yield filename, record.get('id'), record.get('model'), values
|
||
|
||
|
||
def _po_entries(filename):
|
||
entries = []
|
||
context = msgid = msgstr = None
|
||
for line in (MODULE_DIR / filename).read_text(encoding='utf-8').splitlines():
|
||
if line.startswith('msgctxt '):
|
||
context = line.split(' ', 1)[1].strip().strip('"')
|
||
elif line.startswith('msgid '):
|
||
msgid = line.split(' ', 1)[1].strip().strip('"')
|
||
elif line.startswith('msgstr '):
|
||
msgstr = line.split(' ', 1)[1].strip().strip('"')
|
||
entries.append((context, msgid, msgstr))
|
||
context = msgid = msgstr = None
|
||
return entries
|
||
|
||
|
||
class AccountDoTestCase(ModuleTestCase):
|
||
"Test account_do module"
|
||
module = 'account_do'
|
||
|
||
@with_transaction()
|
||
def test_chart_template_is_loaded_by_default(self):
|
||
'Test Dominican chart template is loaded without Spanish language setup'
|
||
pool = Pool()
|
||
ModelData = pool.get('ir.model.data')
|
||
|
||
self.assertTrue(ModelData.get_id('account_do', 'do_account_root'))
|
||
|
||
@with_transaction()
|
||
def test_chart_creates_company_accounts_and_taxes(self):
|
||
'Test Dominican chart creates usable accounts and taxes'
|
||
pool = Pool()
|
||
Account = pool.get('account.account')
|
||
AccountTemplate = pool.get('account.account.template')
|
||
Company = pool.get('company.company')
|
||
Currency = pool.get('currency.currency')
|
||
ModelData = pool.get('ir.model.data')
|
||
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')
|
||
|
||
currency, = Currency.create([{
|
||
'name': 'Dominican Peso',
|
||
'code': 'DOP',
|
||
'symbol': 'RD$',
|
||
'digits': 2,
|
||
'rounding': '0.01',
|
||
}])
|
||
party, = Party.create([{
|
||
'name': 'Empresa Dominicana',
|
||
}])
|
||
company, = Company.create([{
|
||
'party': party.id,
|
||
'currency': currency.id,
|
||
}])
|
||
template = AccountTemplate(ModelData.get_id(
|
||
'account_do', 'do_account_root'))
|
||
|
||
session_id, _start, _end = CreateChart.create()
|
||
chart = CreateChart(session_id)
|
||
chart.account.account_template = template
|
||
chart.account.company = company
|
||
chart.transition_create_account()
|
||
|
||
receivable, = Account.search([
|
||
('company', '=', company.id),
|
||
('code', '=', '110201'),
|
||
('type.receivable', '=', True),
|
||
('party_required', '=', True),
|
||
('closed', '!=', True),
|
||
], limit=1)
|
||
payable, = Account.search([
|
||
('company', '=', company.id),
|
||
('code', '=', '210101'),
|
||
('type.payable', '=', True),
|
||
('party_required', '=', True),
|
||
('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',
|
||
'210201', '210202', '210203', '210206', '210207',
|
||
'210208', '210209', '210210', '210211', '210212',
|
||
'210213', '210214', '210215', '210216', '210217',
|
||
'210218', '210219',
|
||
'21020101', '21020102', '21020103', '21020104',
|
||
'21020105', '21020201', '21020501', '21020502',
|
||
'21020601', '21020701', '21020702', '21020801',
|
||
'21020802', '21020803', '21020804', '21020805',
|
||
'21020901', '21021001', '21021101', '21021201',
|
||
'21021301', '21021302', '21021401', '21021501',
|
||
'21021502', '21021701', '21021801', '21021901',
|
||
'21021902', '6208']:
|
||
with self.subTest(code=code):
|
||
self.assertTrue(Account.search([
|
||
('company', '=', company.id),
|
||
('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),
|
||
])), 200)
|
||
self.assertGreaterEqual(len(Tax.search([
|
||
('company', '=', company.id),
|
||
])), 25)
|
||
self.assertTrue(TaxCode.search([
|
||
('company', '=', company.id),
|
||
('name', '=', 'ITBIS — Balance Neto (Débito − Crédito)'),
|
||
], limit=1))
|
||
self.assertTrue(TaxRule.search([
|
||
('company', '=', company.id),
|
||
('kind', '=', 'sale'),
|
||
], limit=1))
|
||
self.assertTrue(TaxRule.search([
|
||
('company', '=', company.id),
|
||
('kind', '=', 'purchase'),
|
||
], limit=1))
|
||
self.assertTrue(Tax.search([
|
||
('company', '=', company.id),
|
||
('description', '=', 'ITBIS 18% Ventas'),
|
||
('tax_kind', '=', 'itbis'),
|
||
('rate', '=', Decimal('0.18')),
|
||
], limit=1))
|
||
self.assertTrue(Tax.search([
|
||
('company', '=', company.id),
|
||
('description', '=', 'Retención ITBIS Gran Contribuyente 30%'),
|
||
('tax_kind', '=', 'itbis_withholding'),
|
||
('tax_fiscal_type', '=', 'itbis_withholding_30'),
|
||
('rate', '=', Decimal('-0.054')),
|
||
], limit=1))
|
||
self.assertTrue(Tax.search([
|
||
('company', '=', company.id),
|
||
('description', '=', 'Retención ITBIS Proveedor Informal 75%'),
|
||
('tax_kind', '=', 'itbis_withholding'),
|
||
('tax_fiscal_type', '=', 'itbis_withholding_75_informal'),
|
||
('rate', '=', Decimal('-0.135')),
|
||
], limit=1))
|
||
check_015, = Tax.search([
|
||
('company', '=', company.id),
|
||
('description', '=', 'Impuesto Cheques y Transferencias 0.15%'),
|
||
], limit=1)
|
||
check_020, = Tax.search([
|
||
('company', '=', company.id),
|
||
('description', '=', 'Impuesto Cheques y Transferencias 0.20%'),
|
||
], limit=1)
|
||
bank_rule, = TaxRule.search([
|
||
('company', '=', company.id),
|
||
('name', '=', (
|
||
'Regla Bancaria Cheques / Transferencias '
|
||
'Electrónicas (RD)')),
|
||
], limit=1)
|
||
self.assertEqual(check_015.end_date, datetime.date(2026, 7, 2))
|
||
self.assertEqual(check_015.dgii_fiscal_status, 'historical')
|
||
self.assertEqual(check_020.start_date, datetime.date(2026, 7, 3))
|
||
self.assertEqual(check_020.dgii_fiscal_status, 'current')
|
||
self.assertEqual(
|
||
bank_rule.apply(check_015, {
|
||
'date': datetime.date(2026, 7, 2),
|
||
}),
|
||
[check_015.id])
|
||
self.assertEqual(
|
||
bank_rule.apply(check_015, {
|
||
'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
|
||
chart.properties.account_payable = payable
|
||
with Transaction().set_context(company=company.id):
|
||
chart.transition_create_properties()
|
||
CreateChart.delete(session_id)
|
||
|
||
|
||
class AccountDoUnitTestCase(unittest.TestCase):
|
||
|
||
def test_static_project_configuration_is_complete(self):
|
||
config = ConfigParser()
|
||
config.read(MODULE_DIR / 'tryton.cfg', encoding='utf-8')
|
||
|
||
def lines(section, option):
|
||
return [
|
||
line.strip()
|
||
for line in config.get(section, option).splitlines()
|
||
if line.strip()
|
||
]
|
||
|
||
self.assertEqual(config.get('tryton', 'version'), '8.0.0')
|
||
self.assertEqual(
|
||
set(lines('tryton', 'depends')),
|
||
{'account', 'company', 'currency'})
|
||
self.assertEqual(
|
||
lines('tryton', 'xml'),
|
||
[
|
||
'account_chart_do.xml',
|
||
'tax_do.xml',
|
||
'tax_view.xml',
|
||
'tax_code_do.xml',
|
||
'tax_rule_do.xml',
|
||
])
|
||
self.assertEqual(
|
||
lines('register', 'model'),
|
||
[
|
||
'tax.TaxTemplate',
|
||
'tax.Tax',
|
||
'tax.TaxCode',
|
||
'tax.TaxCodeLine',
|
||
])
|
||
for filename in lines('tryton', 'xml'):
|
||
self.assertTrue((MODULE_DIR / filename).is_file())
|
||
|
||
pyproject = (MODULE_DIR / 'pyproject.toml').read_text(encoding='utf-8')
|
||
self.assertIn("name = 'trytond_account_do'", pyproject)
|
||
self.assertIn(
|
||
"account_do = 'trytond.modules.account_do'", pyproject)
|
||
for package_file in [
|
||
'README.rst',
|
||
'IMPUESTOS_RD.md',
|
||
'doc/**/*.rst',
|
||
'locale/**/*.po',
|
||
'tests/**/*.rst',
|
||
]:
|
||
self.assertIn(package_file, pyproject)
|
||
self.assertEqual(
|
||
(MODULE_DIR / '__init__.py').read_text(encoding='utf-8'), '')
|
||
|
||
def test_xml_record_inventory_is_explicit(self):
|
||
expected = {
|
||
'account_chart_do.xml': {
|
||
'account.account.type.template': 36,
|
||
'account.account.template': 281,
|
||
},
|
||
'tax_do.xml': {
|
||
'account.tax.group': 7,
|
||
'account.tax.template': 55,
|
||
},
|
||
'tax_code_do.xml': {
|
||
'account.tax.code.template': 49,
|
||
'account.tax.code.line.template': 103,
|
||
},
|
||
'tax_rule_do.xml': {
|
||
'account.tax.rule.template': 28,
|
||
'account.tax.rule.line.template': 35,
|
||
},
|
||
'tax_view.xml': {
|
||
'ir.ui.view': 4,
|
||
},
|
||
}
|
||
for filename, expected_counts in expected.items():
|
||
records = list(_iter_xml_records(filename))
|
||
with self.subTest(filename=filename):
|
||
self.assertEqual(
|
||
dict(Counter(model for _, _, model, _ in records)),
|
||
expected_counts)
|
||
self.assertFalse([
|
||
(record_id, model)
|
||
for _, record_id, model, _ in records
|
||
if not record_id or not model])
|
||
duplicate_ids = [
|
||
record_id
|
||
for record_id, count in Counter(
|
||
record_id for _, record_id, _, _ in records).items()
|
||
if count > 1]
|
||
self.assertEqual(duplicate_ids, [])
|
||
|
||
def test_gitea_workflow_tests_before_publish(self):
|
||
workflow = (
|
||
MODULE_DIR / '.gitea' / 'workflows' / 'publish.yml'
|
||
).read_text(encoding='utf-8')
|
||
|
||
self.assertIn('test:', workflow)
|
||
self.assertIn('publish:', workflow)
|
||
self.assertIn('needs: test', workflow)
|
||
self.assertIn("python -m pip install '.[test]'", workflow)
|
||
self.assertIn('python -m compileall .', workflow)
|
||
self.assertIn(
|
||
"python -m unittest discover -s tests -p 'test*.py'", workflow)
|
||
self.assertIn('python -m build', workflow)
|
||
self.assertLess(
|
||
workflow.index('test:'),
|
||
workflow.index('publish:'))
|
||
self.assertLess(
|
||
workflow.index("python -m unittest discover -s tests -p 'test*.py'"),
|
||
workflow.index('Set CI package version'))
|
||
|
||
def test_tax_views_expose_all_localization_fields(self):
|
||
localization_fields = [
|
||
'tax_kind',
|
||
'tax_fiscal_type',
|
||
'tax_application',
|
||
'dgii_fiscal_status',
|
||
'dgii_form_hint',
|
||
'dgii_legal_reference',
|
||
'dgii_legal_article',
|
||
]
|
||
form = ET.parse(MODULE_DIR / 'view/tax_form.xml').getroot()
|
||
list_ = ET.parse(MODULE_DIR / 'view/tax_list.xml').getroot()
|
||
form_fields = [
|
||
element.get('name')
|
||
for element in form.findall('.//field')
|
||
if element.get('name') in localization_fields
|
||
]
|
||
list_fields = [
|
||
element.get('name')
|
||
for element in list_.findall('.//field')
|
||
if element.get('name') in localization_fields
|
||
]
|
||
self.assertEqual(form_fields, localization_fields)
|
||
self.assertEqual(list_fields, localization_fields[:3])
|
||
|
||
view_records = {
|
||
(values['model'], values['name'], values['inherit'])
|
||
for _, _, model, values in _iter_xml_records('tax_view.xml')
|
||
if model == 'ir.ui.view'
|
||
}
|
||
self.assertEqual(view_records, {
|
||
('account.tax.template', 'tax_form',
|
||
'account.tax_template_view_form'),
|
||
('account.tax', 'tax_form', 'account.tax_view_form'),
|
||
('account.tax.template', 'tax_list',
|
||
'account.tax_template_view_list'),
|
||
('account.tax', 'tax_list', 'account.tax_view_list'),
|
||
})
|
||
|
||
def test_translation_catalogs_cover_module_terms(self):
|
||
type_templates = {
|
||
record_id: values['name']
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'account_chart_do.xml')
|
||
if model == 'account.account.type.template'
|
||
}
|
||
account_templates = {
|
||
record_id: values['name']
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'account_chart_do.xml')
|
||
if model == 'account.account.template'
|
||
}
|
||
required_field_contexts = {
|
||
'field:account.tax,tax_kind:',
|
||
'field:account.tax.template,tax_kind:',
|
||
'field:account.tax,tax_fiscal_type:',
|
||
'field:account.tax.template,tax_fiscal_type:',
|
||
'field:account.tax,tax_application:',
|
||
'field:account.tax.template,tax_application:',
|
||
'field:account.tax,dgii_fiscal_status:',
|
||
'field:account.tax.template,dgii_fiscal_status:',
|
||
'field:account.tax,dgii_form_hint:',
|
||
'field:account.tax.template,dgii_form_hint:',
|
||
'field:account.tax,dgii_legal_article:',
|
||
'field:account.tax.template,dgii_legal_article:',
|
||
'field:account.tax,dgii_legal_reference:',
|
||
'field:account.tax.template,dgii_legal_reference:',
|
||
}
|
||
for filename in ['locale/es.po', 'locale/es_419.po']:
|
||
entries = _po_entries(filename)
|
||
contexts = {context for context, _msgid, _msgstr in entries}
|
||
entry_keys = [(context, msgid) for context, msgid, _ in entries]
|
||
with self.subTest(filename=filename):
|
||
self.assertEqual(
|
||
[key for key, count in Counter(entry_keys).items()
|
||
if count > 1],
|
||
[])
|
||
self.assertLessEqual(required_field_contexts, contexts)
|
||
for record_id in type_templates:
|
||
self.assertIn(
|
||
'model:account.account.type.template,name:%s'
|
||
% record_id,
|
||
contexts)
|
||
for record_id in [
|
||
'do_account_110201',
|
||
'do_account_210101',
|
||
'do_account_21021901',
|
||
'do_account_21021902',
|
||
]:
|
||
self.assertIn(
|
||
'model:account.account.template,name:%s' % record_id,
|
||
contexts)
|
||
|
||
def test_migration_metadata_is_explicit(self):
|
||
from trytond.modules.account_do.tax import (
|
||
MODEL_DATA_RENAMES, ROOT_TAX_CODE_CHILDREN)
|
||
|
||
self.assertEqual(MODEL_DATA_RENAMES, {
|
||
'do_tax_group_otros': 'do_tax_group_others',
|
||
'do_tc_otros': 'do_tc_others',
|
||
'do_tc_otros_propina': 'do_tc_others_tip',
|
||
'do_tc_otros_cheques': 'do_tc_others_checks',
|
||
'do_tc_otros_activos': 'do_tc_others_assets',
|
||
'do_tc_otros_iti': 'do_tc_others_iti',
|
||
})
|
||
self.assertEqual(ROOT_TAX_CODE_CHILDREN, [
|
||
'ITBIS — Balance Neto (Débito − Crédito)',
|
||
'ISR - Retenciones',
|
||
'ISR - Retenciones en la Fuente',
|
||
'ISC - Impuesto Selectivo al Consumo',
|
||
'CDT INDOTEL 2% (Ley 153-98)',
|
||
'Otros Impuestos y Contribuciones',
|
||
])
|
||
|
||
def test_xml_references_are_resolved_inside_module(self):
|
||
records = list(_iter_xml_records(
|
||
'account_chart_do.xml',
|
||
'tax_do.xml',
|
||
'tax_code_do.xml',
|
||
'tax_rule_do.xml',
|
||
))
|
||
ids = {record_id for _, record_id, _, _ in records}
|
||
missing = []
|
||
for filename in [
|
||
'account_chart_do.xml',
|
||
'tax_do.xml',
|
||
'tax_code_do.xml',
|
||
'tax_rule_do.xml',
|
||
]:
|
||
root = ET.parse(MODULE_DIR / filename).getroot()
|
||
for record in root.findall('.//record'):
|
||
for field in record.findall('field'):
|
||
ref = field.get('ref')
|
||
if ref and '.' not in ref and ref not in ids:
|
||
missing.append(
|
||
(filename, record.get('id'), field.get('name'), ref))
|
||
self.assertEqual(missing, [])
|
||
|
||
def test_chart_template_codes_are_unique(self):
|
||
accounts = [
|
||
values for _, _, model, values in _iter_xml_records(
|
||
'account_chart_do.xml')
|
||
if model == 'account.account.template'
|
||
]
|
||
codes = [values['code'] for values in accounts if values.get('code')]
|
||
duplicates = [
|
||
code for code, count in Counter(codes).items() if count > 1]
|
||
self.assertEqual(duplicates, [])
|
||
|
||
def test_chart_root_and_statement_classification(self):
|
||
accounts = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'account_chart_do.xml')
|
||
if model == 'account.account.template'
|
||
}
|
||
types = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'account_chart_do.xml')
|
||
if model == 'account.account.type.template'
|
||
}
|
||
|
||
self.assertEqual([
|
||
accounts[f'do_account_{code}']['code']
|
||
for code in range(1, 8)
|
||
], ['1', '2', '3', '4', '5', '6', '7'])
|
||
self.assertEqual(
|
||
types['do_type_retained_earnings']['statement'], 'balance')
|
||
self.assertEqual(types['do_type_revenue']['statement'], 'income')
|
||
self.assertEqual(types['do_type_expense']['statement'], 'income')
|
||
self.assertEqual(
|
||
accounts['do_account_110201']['type'], 'do_type_receivable')
|
||
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
|
||
for _, record_id, _, _ in _iter_xml_records(
|
||
'tax_do.xml', 'tax_code_do.xml')
|
||
}
|
||
self.assertFalse([record_id for record_id in ids if 'otros' in record_id])
|
||
|
||
def test_tax_templates_are_classified(self):
|
||
taxes = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records('tax_do.xml')
|
||
if model == 'account.tax.template'
|
||
}
|
||
accounts = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'account_chart_do.xml')
|
||
if model == 'account.account.template'
|
||
}
|
||
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):
|
||
values = taxes[record_id]
|
||
self.assertEqual(values.get('invoice_account', ''), account_id)
|
||
self.assertEqual(
|
||
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')
|
||
self.assertIn(
|
||
"Decimal('-5.4')/100",
|
||
taxes['do_tax_ret_itbis_30']['rate'])
|
||
self.assertEqual(
|
||
taxes['do_tax_ret_itbis_75_inf']['tax_fiscal_type'],
|
||
'itbis_withholding_75_informal')
|
||
self.assertIn(
|
||
"Decimal('-13.5')/100",
|
||
taxes['do_tax_ret_itbis_75_inf']['rate'])
|
||
for record_id in [
|
||
'do_tax_ret_isr_hon_5',
|
||
'do_tax_ret_isr_serv_10',
|
||
'do_tax_ret_isr_alq_10',
|
||
'do_tax_ret_isr_est_5',
|
||
'do_tax_ret_isr_bovine_1',
|
||
'do_tax_ret_isr_exporter_25',
|
||
'do_tax_ret_isr_ext_27',
|
||
]:
|
||
self.assertIn("Decimal('-", taxes[record_id]['rate'])
|
||
self.assertEqual(
|
||
taxes['do_tax_itbis_9_venta']['tax_fiscal_type'],
|
||
'itbis_sale_9')
|
||
self.assertIn(
|
||
"Decimal('9')/100",
|
||
taxes['do_tax_itbis_9_compra']['rate'])
|
||
self.assertEqual(
|
||
taxes['do_tax_isc_bebidas_alc']['tax_fiscal_type'],
|
||
'isc_alcohol_10')
|
||
self.assertIn(
|
||
"Decimal('10')/100",
|
||
taxes['do_tax_isc_bebidas_alc']['rate'])
|
||
self.assertEqual(
|
||
taxes['do_tax_isc_combustibles_16']['tax_fiscal_type'],
|
||
'isc_fossil_fuel_16')
|
||
self.assertEqual(
|
||
taxes['do_tax_cheques_020']['tax_kind'], 'others')
|
||
self.assertEqual(
|
||
taxes['do_tax_cheques_015']['end_date'],
|
||
'datetime.date(2026, 7, 2)')
|
||
self.assertEqual(
|
||
taxes['do_tax_cheques_015']['dgii_fiscal_status'],
|
||
'historical')
|
||
self.assertEqual(
|
||
taxes['do_tax_cheques_020']['start_date'],
|
||
'datetime.date(2026, 7, 3)')
|
||
self.assertEqual(
|
||
taxes['do_tax_cheques_020']['dgii_fiscal_status'],
|
||
'current')
|
||
self.assertEqual(
|
||
taxes['do_tax_cheques_020']['invoice_account'],
|
||
'do_account_21021902')
|
||
self.assertIn(
|
||
"Decimal('0.20')/100",
|
||
taxes['do_tax_cheques_020']['rate'])
|
||
|
||
def test_tax_code_templates_use_expected_signs(self):
|
||
codes = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'tax_code_do.xml')
|
||
if model == 'account.tax.code.template'
|
||
}
|
||
lines = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'tax_code_do.xml')
|
||
if model == 'account.tax.code.line.template'
|
||
}
|
||
for record_id in [
|
||
'do_tc_itbis',
|
||
'do_tc_isr',
|
||
'do_tc_isc',
|
||
'do_tc_cdt',
|
||
'do_tc_others',
|
||
]:
|
||
self.assertEqual(codes[record_id].get('parent'), 'None')
|
||
self.assertEqual(codes['do_tc_isr']['name'], 'ISR - Retenciones')
|
||
self.assertEqual(
|
||
lines['do_tcl_isr_int_pf_inv']['code'],
|
||
'do_tc_isr_intereses_pf')
|
||
self.assertEqual(
|
||
lines['do_tcl_isr_int_pf_cr']['code'],
|
||
'do_tc_isr_intereses_pf')
|
||
self.assertEqual(
|
||
lines['do_tcl_isr_int_pj_inv']['code'],
|
||
'do_tc_isr_intereses')
|
||
self.assertEqual(
|
||
lines['do_tcl_isr_int_pj_cr']['code'],
|
||
'do_tc_isr_intereses')
|
||
self.assertEqual(
|
||
lines['do_tcl_chq020_inv']['code'],
|
||
'do_tc_others_checks_020')
|
||
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'], '+')
|
||
self.assertEqual(lines['do_tcl_itbis9c_inv']['operator'], '-')
|
||
self.assertEqual(lines['do_tcl_ret_itbis_inv']['operator'], '-')
|
||
self.assertEqual(lines['do_tcl_ret_itbis_adq_inv']['operator'], '+')
|
||
self.assertEqual(lines['do_tcl_ret_itbis_inf75_inv']['operator'], '-')
|
||
self.assertEqual(lines['do_tcl_isr_hon_inv']['operator'], '-')
|
||
self.assertEqual(lines['do_tcl_isr_est_inv']['operator'], '+')
|
||
self.assertEqual(lines['do_tcl_isr_est5_inv']['operator'], '+')
|
||
self.assertEqual(lines['do_tcl_isr_bovine_inv']['operator'], '-')
|
||
self.assertEqual(lines['do_tcl_isr_exporter_inv']['operator'], '+')
|
||
self.assertEqual(lines['do_tcl_isc_comb_inv']['operator'], '+')
|
||
self.assertEqual(lines['do_tcl_prop_inv']['code'], 'do_tc_others_tip')
|
||
|
||
def test_tax_rule_templates_include_date_sensitive_bank_tax(self):
|
||
rules = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'tax_rule_do.xml')
|
||
if model == 'account.tax.rule.template'
|
||
}
|
||
lines = {
|
||
record_id: values
|
||
for _, record_id, model, values in _iter_xml_records(
|
||
'tax_rule_do.xml')
|
||
if model == 'account.tax.rule.line.template'
|
||
}
|
||
self.assertIn('do_tax_rule_bank_check_transfer', rules)
|
||
self.assertEqual(
|
||
lines['do_trline_bank_check_transfer_015']['origin_tax'],
|
||
'do_tax_cheques_015')
|
||
self.assertEqual(
|
||
lines['do_trline_bank_check_transfer_015']['tax'],
|
||
'do_tax_cheques_015')
|
||
self.assertEqual(
|
||
lines['do_trline_bank_check_transfer_015']['end_date'],
|
||
'datetime.date(2026, 7, 2)')
|
||
self.assertEqual(
|
||
lines['do_trline_bank_check_transfer_020']['origin_tax'],
|
||
'do_tax_cheques_015')
|
||
self.assertEqual(
|
||
lines['do_trline_bank_check_transfer_020']['tax'],
|
||
'do_tax_cheques_020')
|
||
self.assertEqual(
|
||
lines['do_trline_bank_check_transfer_020']['start_date'],
|
||
'datetime.date(2026, 7, 3)')
|
||
|
||
def test_tax_kind_contains_dominican_tax_categories(self):
|
||
codes = {code for code, _ in TAX_KIND}
|
||
self.assertEqual(codes, {
|
||
'',
|
||
'itbis',
|
||
'itbis_withholding',
|
||
'itbis_withholding_acquirer',
|
||
'isr_withholding',
|
||
'isc',
|
||
'cdt',
|
||
'tip',
|
||
'others',
|
||
})
|
||
|
||
def test_tax_kind_codes_are_unique(self):
|
||
codes = [code for code, _ in TAX_KIND]
|
||
self.assertEqual(len(codes), len(set(codes)))
|
||
|
||
def test_fiscal_classification_codes_are_unique(self):
|
||
fiscal_codes = [code for code, _ in TAX_FISCAL_TYPE]
|
||
application_codes = [code for code, _ in TAX_APPLICATION]
|
||
status_codes = [code for code, _ in DGII_FISCAL_STATUS]
|
||
self.assertEqual(len(fiscal_codes), len(set(fiscal_codes)))
|
||
self.assertEqual(len(application_codes), len(set(application_codes)))
|
||
self.assertEqual(len(status_codes), len(set(status_codes)))
|
||
|
||
|
||
del ModuleTestCase
|