2026-07-22 21:27:53 -04:00
|
|
|
import datetime
|
|
|
|
|
from decimal import Decimal
|
|
|
|
|
from types import SimpleNamespace
|
|
|
|
|
import unittest
|
|
|
|
|
|
2026-07-22 21:52:32 -04:00
|
|
|
from trytond.exceptions import UserError
|
2026-07-22 21:27:53 -04:00
|
|
|
from trytond.modules.ncf_manager.sequence import Sequence
|
|
|
|
|
from trytond.modules.ncf_manager.invoice import Invoice
|
|
|
|
|
from trytond.pool import Pool
|
|
|
|
|
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
|
|
|
|
from trytond.transaction import Transaction
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NcfManagerTestCase(ModuleTestCase):
|
|
|
|
|
"Test Ncf Manager module"
|
|
|
|
|
module = 'ncf_manager'
|
|
|
|
|
|
|
|
|
|
def _create_company(self):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Company = pool.get('company.company')
|
|
|
|
|
Currency = pool.get('currency.currency')
|
|
|
|
|
Party = pool.get('party.party')
|
|
|
|
|
|
|
|
|
|
currency, = Currency.create([{
|
|
|
|
|
'name': 'Dominican Peso',
|
|
|
|
|
'code': 'DOP',
|
|
|
|
|
'symbol': 'RD$',
|
|
|
|
|
'digits': 2,
|
|
|
|
|
'rounding': '0.01',
|
|
|
|
|
}])
|
|
|
|
|
party, = Party.create([{
|
|
|
|
|
'name': 'Empresa NCF',
|
|
|
|
|
'addresses': [('create', [{}])],
|
|
|
|
|
}])
|
|
|
|
|
company, = Company.create([{
|
|
|
|
|
'party': party.id,
|
|
|
|
|
'currency': currency.id,
|
|
|
|
|
}])
|
|
|
|
|
return company
|
|
|
|
|
|
|
|
|
|
def _create_chart(self, company):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Account = pool.get('account.account')
|
|
|
|
|
AccountTemplate = pool.get('account.account.template')
|
|
|
|
|
CreateChart = pool.get('account.create_chart', type='wizard')
|
|
|
|
|
Journal = pool.get('account.journal')
|
|
|
|
|
ModelData = pool.get('ir.model.data')
|
|
|
|
|
|
|
|
|
|
session_id, _start, _end = CreateChart.create()
|
|
|
|
|
chart = CreateChart(session_id)
|
|
|
|
|
chart.account.account_template = AccountTemplate(ModelData.get_id(
|
|
|
|
|
'account_do', 'do_account_root'))
|
|
|
|
|
chart.account.company = company
|
|
|
|
|
chart.transition_create_account()
|
|
|
|
|
|
|
|
|
|
receivable, = Account.search([
|
|
|
|
|
('company', '=', company.id),
|
|
|
|
|
('code', '=', '110201'),
|
|
|
|
|
], limit=1)
|
|
|
|
|
payable, = Account.search([
|
|
|
|
|
('company', '=', company.id),
|
|
|
|
|
('code', '=', '210101'),
|
|
|
|
|
], limit=1)
|
|
|
|
|
revenue, = Account.search([
|
|
|
|
|
('company', '=', company.id),
|
|
|
|
|
('code', '=', '4102'),
|
|
|
|
|
], limit=1)
|
|
|
|
|
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)
|
|
|
|
|
journal, = Journal.search([('type', '=', 'revenue')], limit=1)
|
|
|
|
|
return receivable, revenue, journal
|
|
|
|
|
|
|
|
|
|
def _create_fiscalyear(self, company, today=None):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
FiscalYear = pool.get('account.fiscalyear')
|
|
|
|
|
InvoiceSequence = pool.get('account.fiscalyear.invoice_sequence')
|
|
|
|
|
StrictSequence = pool.get('ir.sequence.strict')
|
|
|
|
|
SequenceType = pool.get('ir.sequence.type')
|
|
|
|
|
today = today or datetime.date.today()
|
|
|
|
|
year = today.year
|
|
|
|
|
|
|
|
|
|
move_type, = SequenceType.search([
|
|
|
|
|
('name', '=', 'Account Move'),
|
|
|
|
|
], limit=1)
|
|
|
|
|
invoice_type, = SequenceType.search([
|
|
|
|
|
('name', '=', 'Invoice'),
|
|
|
|
|
], limit=1)
|
|
|
|
|
move_sequence, = StrictSequence.create([{
|
|
|
|
|
'name': 'FY 2026 Moves',
|
|
|
|
|
'sequence_type': move_type.id,
|
|
|
|
|
'company': company.id,
|
|
|
|
|
}])
|
|
|
|
|
invoice_sequence, = StrictSequence.create([{
|
|
|
|
|
'name': 'FY 2026 Invoices',
|
|
|
|
|
'sequence_type': invoice_type.id,
|
|
|
|
|
'company': company.id,
|
|
|
|
|
}])
|
|
|
|
|
fiscalyear, = FiscalYear.create([{
|
|
|
|
|
'name': str(year),
|
|
|
|
|
'start_date': datetime.date(year, 1, 1),
|
|
|
|
|
'end_date': datetime.date(year, 12, 31),
|
|
|
|
|
'company': company.id,
|
|
|
|
|
'move_sequence': move_sequence.id,
|
|
|
|
|
}])
|
|
|
|
|
fiscalyear.invoice_sequences = [InvoiceSequence(
|
|
|
|
|
company=company,
|
|
|
|
|
in_invoice_sequence=invoice_sequence,
|
|
|
|
|
in_credit_note_sequence=invoice_sequence,
|
|
|
|
|
out_invoice_sequence=invoice_sequence,
|
|
|
|
|
out_credit_note_sequence=invoice_sequence)]
|
|
|
|
|
fiscalyear.save()
|
|
|
|
|
FiscalYear.create_period([fiscalyear])
|
|
|
|
|
|
|
|
|
|
def _create_payment_term(self):
|
|
|
|
|
PaymentTerm = Pool().get('account.invoice.payment_term')
|
|
|
|
|
term, = PaymentTerm.create([{
|
|
|
|
|
'name': 'Contado',
|
|
|
|
|
'lines': [('create', [{'type': 'remainder'}])],
|
|
|
|
|
}])
|
|
|
|
|
return term
|
|
|
|
|
|
|
|
|
|
def _create_ncf_sequence(self, company, today=None):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
ModelData = pool.get('ir.model.data')
|
|
|
|
|
Manager = pool.get('ncf.manager')
|
|
|
|
|
ManagerSequence = pool.get('ncf.manager.sequence')
|
|
|
|
|
StrictSequence = pool.get('ir.sequence.strict')
|
|
|
|
|
SequenceType = pool.get('ir.sequence.type')
|
|
|
|
|
today = today or datetime.date.today()
|
|
|
|
|
|
|
|
|
|
sequence_type = SequenceType(ModelData.get_id(
|
|
|
|
|
'ncf_manager', 'sequence_type_out_invoice_01'))
|
|
|
|
|
strict_sequence, = StrictSequence.create([{
|
|
|
|
|
'name': 'B01 Factura Credito Fiscal',
|
|
|
|
|
'sequence_type': sequence_type.id,
|
|
|
|
|
'company': company.id,
|
|
|
|
|
'prefix': 'B01',
|
|
|
|
|
'padding': 8,
|
|
|
|
|
'number_next': 1,
|
|
|
|
|
'number_increment': 1,
|
|
|
|
|
'from_number': 1,
|
|
|
|
|
'until_number': 2,
|
|
|
|
|
'expiration_date': datetime.date(today.year, 12, 31),
|
|
|
|
|
}])
|
|
|
|
|
manager, = Manager.create([{
|
|
|
|
|
'company': company.id,
|
|
|
|
|
'app_date': datetime.date(today.year, 1, 1),
|
|
|
|
|
'app_number': '0000000001',
|
|
|
|
|
'auth_number': '0000000001',
|
|
|
|
|
'state': 'active',
|
|
|
|
|
}])
|
|
|
|
|
with Transaction().set_context(company=company.id):
|
|
|
|
|
sequence, = ManagerSequence.create([{
|
|
|
|
|
'pos': manager.id,
|
|
|
|
|
'ncf_type': '1',
|
|
|
|
|
'ncf_sequences': strict_sequence.id,
|
|
|
|
|
'invoice_type': 'invoice_customer',
|
|
|
|
|
'state': 'active',
|
|
|
|
|
}])
|
|
|
|
|
return sequence
|
|
|
|
|
|
|
|
|
|
@with_transaction()
|
|
|
|
|
def test_customer_invoice_post_assigns_b01_ncf(self):
|
|
|
|
|
'Test full NCF assignment workflow on posted customer invoice'
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Invoice = pool.get('account.invoice')
|
|
|
|
|
Party = pool.get('party.party')
|
|
|
|
|
|
|
|
|
|
today = datetime.date.today()
|
|
|
|
|
company = self._create_company()
|
|
|
|
|
receivable, revenue, journal = self._create_chart(company)
|
|
|
|
|
self._create_fiscalyear(company, today=today)
|
|
|
|
|
payment_term = self._create_payment_term()
|
|
|
|
|
ncf_sequence = self._create_ncf_sequence(company, today=today)
|
|
|
|
|
party, = Party.create([{
|
|
|
|
|
'name': 'Cliente NCF',
|
|
|
|
|
'addresses': [('create', [{}])],
|
|
|
|
|
}])
|
|
|
|
|
|
|
|
|
|
with Transaction().set_context(
|
|
|
|
|
company=company.id, date=today):
|
|
|
|
|
invoice, = Invoice.create([{
|
|
|
|
|
'type': 'out',
|
|
|
|
|
'company': company.id,
|
|
|
|
|
'party': party.id,
|
|
|
|
|
'invoice_address': party.addresses[0].id,
|
|
|
|
|
'account': receivable.id,
|
|
|
|
|
'currency': company.currency.id,
|
|
|
|
|
'invoice_date': today,
|
|
|
|
|
'accounting_date': today,
|
|
|
|
|
'journal': journal.id,
|
|
|
|
|
'payment_term': payment_term.id,
|
|
|
|
|
'ncf_type': '1',
|
|
|
|
|
'ncf_sequence': ncf_sequence.id,
|
|
|
|
|
'revenue_type': '01',
|
|
|
|
|
'payment_method': '04',
|
|
|
|
|
'lines': [('create', [{
|
|
|
|
|
'type': 'line',
|
|
|
|
|
'description': 'Servicio',
|
|
|
|
|
'quantity': 1,
|
|
|
|
|
'unit_price': Decimal('500.00'),
|
|
|
|
|
'account': revenue.id,
|
|
|
|
|
}])],
|
|
|
|
|
}])
|
|
|
|
|
Invoice.post([invoice])
|
|
|
|
|
invoice = Invoice(invoice.id)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(invoice.state, 'posted')
|
|
|
|
|
self.assertEqual(invoice.ncf_number, 'B0100000001')
|
|
|
|
|
self.assertEqual(invoice.ncf_sequence, ncf_sequence)
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
invoice.expiration_date, datetime.date(today.year, 12, 31))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
del ModuleTestCase
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NcfManagerUnitTestCase(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_sequence_defaults_match_ncf_type(self):
|
|
|
|
|
sequence = SimpleNamespace(
|
|
|
|
|
sequence_type=SimpleNamespace(name='Factura de Crédito Fiscal'))
|
|
|
|
|
|
|
|
|
|
self.assertEqual(Sequence.on_change_with_prefix(sequence), 'B01')
|
|
|
|
|
self.assertEqual(Sequence.on_change_with_padding(sequence), 8)
|
|
|
|
|
|
|
|
|
|
def test_sequence_approved_and_remaining_quantities(self):
|
|
|
|
|
sequence = SimpleNamespace(
|
|
|
|
|
from_number=1,
|
|
|
|
|
until_number=10,
|
|
|
|
|
number_next=4)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(Sequence.on_change_with_approved_qty(sequence), 10)
|
|
|
|
|
self.assertEqual(Sequence.on_change_with_remaining_qty(sequence), 7)
|
|
|
|
|
|
2026-07-22 21:52:32 -04:00
|
|
|
def test_fiscal_cancellation_requires_ncf_number(self):
|
|
|
|
|
fiscal_invoice = SimpleNamespace(type='out', ncf_number='B0100000001')
|
|
|
|
|
non_fiscal_invoice = SimpleNamespace(type='out', ncf_number=None)
|
|
|
|
|
supplier_invoice = SimpleNamespace(type='in', ncf_number='B1100000001')
|
|
|
|
|
|
|
|
|
|
self.assertTrue(
|
|
|
|
|
Invoice._ncf_is_fiscal_cancellation_required(fiscal_invoice))
|
|
|
|
|
self.assertFalse(
|
|
|
|
|
Invoice._ncf_is_fiscal_cancellation_required(non_fiscal_invoice))
|
|
|
|
|
self.assertFalse(
|
|
|
|
|
Invoice._ncf_is_fiscal_cancellation_required(supplier_invoice))
|
|
|
|
|
|
|
|
|
|
def test_fiscal_cancellation_information_is_required(self):
|
|
|
|
|
invoice = SimpleNamespace(
|
|
|
|
|
type='out',
|
|
|
|
|
rec_name='INV/1',
|
|
|
|
|
ncf_number='B0100000001',
|
|
|
|
|
ncf_cancellation_type=None,
|
|
|
|
|
ncf_cancellation_reason=None)
|
|
|
|
|
|
|
|
|
|
with self.assertRaises(UserError):
|
|
|
|
|
Invoice._ncf_check_cancellation_information(invoice)
|
|
|
|
|
|
|
|
|
|
invoice.ncf_cancellation_type = '04'
|
|
|
|
|
with self.assertRaises(UserError):
|
|
|
|
|
Invoice._ncf_check_cancellation_information(invoice)
|
|
|
|
|
|
|
|
|
|
invoice.ncf_cancellation_reason = 'Corrección de la información'
|
|
|
|
|
Invoice._ncf_check_cancellation_information(invoice)
|
|
|
|
|
|
2026-07-22 21:27:53 -04:00
|
|
|
def test_debit_note_code_follows_origin_ncf_type(self):
|
|
|
|
|
original_enabled = Invoice._ncf_electronic_invoicing_enabled
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = classmethod(
|
|
|
|
|
lambda cls: False)
|
|
|
|
|
try:
|
|
|
|
|
physical = SimpleNamespace(ncf_type='1')
|
|
|
|
|
electronic = SimpleNamespace(ncf_type='31')
|
|
|
|
|
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
Invoice._ncf_resolve_debit_note_code(physical), '3')
|
|
|
|
|
self.assertEqual(
|
|
|
|
|
Invoice._ncf_resolve_debit_note_code(electronic), '3')
|
|
|
|
|
finally:
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = original_enabled
|
|
|
|
|
|
|
|
|
|
def test_debit_note_preparation_uses_physical_without_electronic_module(self):
|
|
|
|
|
electronic_sequence = SimpleNamespace(ncf_type='33')
|
|
|
|
|
physical_sequence = SimpleNamespace(ncf_type='3')
|
|
|
|
|
original_find_active_sequence = Invoice._ncf_find_active_sequence
|
|
|
|
|
original_enabled = Invoice._ncf_electronic_invoicing_enabled
|
|
|
|
|
|
|
|
|
|
def find_sequence(cls, invoice, ncf_code):
|
|
|
|
|
if ncf_code == '33':
|
|
|
|
|
return electronic_sequence
|
|
|
|
|
if ncf_code == '3':
|
|
|
|
|
return physical_sequence
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_find_active_sequence = classmethod(find_sequence)
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = classmethod(
|
|
|
|
|
lambda cls: False)
|
|
|
|
|
try:
|
|
|
|
|
origin = SimpleNamespace(
|
|
|
|
|
ncf_number='B0100000001',
|
|
|
|
|
ncf_type='1',
|
|
|
|
|
payment_method='04',
|
|
|
|
|
revenue_type='01',
|
|
|
|
|
isr_withholding_type=None)
|
|
|
|
|
debit_note = SimpleNamespace(
|
|
|
|
|
company=SimpleNamespace(rec_name='Solutema'),
|
|
|
|
|
type='out',
|
|
|
|
|
ncf_number_modified=None,
|
|
|
|
|
ncf_type=None,
|
|
|
|
|
ncf_sequence=None,
|
|
|
|
|
payment_method=None,
|
|
|
|
|
revenue_type=None,
|
|
|
|
|
isr_withholding_type=None)
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_prepare_debit_note_from_origin(origin, debit_note)
|
|
|
|
|
finally:
|
|
|
|
|
Invoice._ncf_find_active_sequence = original_find_active_sequence
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = original_enabled
|
|
|
|
|
|
|
|
|
|
self.assertEqual(debit_note.ncf_number_modified, 'B0100000001')
|
|
|
|
|
self.assertEqual(debit_note.ncf_type, '3')
|
|
|
|
|
self.assertEqual(debit_note.ncf_sequence, physical_sequence)
|
|
|
|
|
self.assertEqual(debit_note.payment_method, '04')
|
|
|
|
|
self.assertEqual(debit_note.revenue_type, '01')
|
|
|
|
|
|
|
|
|
|
def test_debit_note_preparation_prefers_electronic_when_module_is_active(self):
|
|
|
|
|
electronic_sequence = SimpleNamespace(ncf_type='33')
|
|
|
|
|
original_find_active_sequence = Invoice._ncf_find_active_sequence
|
|
|
|
|
original_enabled = Invoice._ncf_electronic_invoicing_enabled
|
|
|
|
|
|
|
|
|
|
def find_sequence(cls, invoice, ncf_code):
|
|
|
|
|
return electronic_sequence if ncf_code == '33' else None
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_find_active_sequence = classmethod(find_sequence)
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = classmethod(
|
|
|
|
|
lambda cls: True)
|
|
|
|
|
try:
|
|
|
|
|
origin = SimpleNamespace(
|
|
|
|
|
ncf_number='B0100000001',
|
|
|
|
|
ncf_type='1',
|
|
|
|
|
payment_method='04',
|
|
|
|
|
revenue_type='01',
|
|
|
|
|
isr_withholding_type=None)
|
|
|
|
|
debit_note = SimpleNamespace(
|
|
|
|
|
company=SimpleNamespace(rec_name='Solutema'),
|
|
|
|
|
type='out',
|
|
|
|
|
ncf_number_modified=None,
|
|
|
|
|
ncf_type=None,
|
|
|
|
|
ncf_sequence=None,
|
|
|
|
|
payment_method=None,
|
|
|
|
|
revenue_type=None,
|
|
|
|
|
isr_withholding_type=None)
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_prepare_debit_note_from_origin(origin, debit_note)
|
|
|
|
|
finally:
|
|
|
|
|
Invoice._ncf_find_active_sequence = original_find_active_sequence
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = original_enabled
|
|
|
|
|
|
|
|
|
|
self.assertEqual(debit_note.ncf_number_modified, 'B0100000001')
|
|
|
|
|
self.assertEqual(debit_note.ncf_type, '33')
|
|
|
|
|
self.assertEqual(debit_note.ncf_sequence, electronic_sequence)
|
|
|
|
|
|
|
|
|
|
def test_debit_note_preparation_falls_back_to_physical_sequence(self):
|
|
|
|
|
physical_sequence = SimpleNamespace(ncf_type='3')
|
|
|
|
|
original_find_active_sequence = Invoice._ncf_find_active_sequence
|
|
|
|
|
original_enabled = Invoice._ncf_electronic_invoicing_enabled
|
|
|
|
|
|
|
|
|
|
def find_sequence(cls, invoice, ncf_code):
|
|
|
|
|
return physical_sequence if ncf_code == '3' else None
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_find_active_sequence = classmethod(find_sequence)
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = classmethod(
|
|
|
|
|
lambda cls: True)
|
|
|
|
|
try:
|
|
|
|
|
origin = SimpleNamespace(
|
|
|
|
|
ncf_number='B0100000001',
|
|
|
|
|
ncf_type='1',
|
|
|
|
|
payment_method='04',
|
|
|
|
|
revenue_type='01',
|
|
|
|
|
isr_withholding_type=None)
|
|
|
|
|
debit_note = SimpleNamespace(
|
|
|
|
|
company=SimpleNamespace(rec_name='Solutema'),
|
|
|
|
|
type='out',
|
|
|
|
|
ncf_number_modified=None,
|
|
|
|
|
ncf_type=None,
|
|
|
|
|
ncf_sequence=None,
|
|
|
|
|
payment_method=None,
|
|
|
|
|
revenue_type=None,
|
|
|
|
|
isr_withholding_type=None)
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_prepare_debit_note_from_origin(origin, debit_note)
|
|
|
|
|
finally:
|
|
|
|
|
Invoice._ncf_find_active_sequence = original_find_active_sequence
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = original_enabled
|
|
|
|
|
|
|
|
|
|
self.assertEqual(debit_note.ncf_number_modified, 'B0100000001')
|
|
|
|
|
self.assertEqual(debit_note.ncf_type, '3')
|
|
|
|
|
self.assertEqual(debit_note.ncf_sequence, physical_sequence)
|
|
|
|
|
|
|
|
|
|
def test_credit_note_preparation_prefers_electronic_sequence_for_b_origin(self):
|
|
|
|
|
electronic_sequence = SimpleNamespace(ncf_type='34')
|
|
|
|
|
original_find_active_sequence = Invoice._ncf_find_active_sequence
|
|
|
|
|
original_enabled = Invoice._ncf_electronic_invoicing_enabled
|
|
|
|
|
|
|
|
|
|
def find_sequence(cls, invoice, ncf_code):
|
|
|
|
|
return electronic_sequence if ncf_code == '34' else None
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_find_active_sequence = classmethod(find_sequence)
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = classmethod(
|
|
|
|
|
lambda cls: True)
|
|
|
|
|
try:
|
|
|
|
|
origin = SimpleNamespace(
|
|
|
|
|
ncf_number='B0100000001',
|
|
|
|
|
ncf_type='1')
|
|
|
|
|
credit_note = SimpleNamespace(
|
|
|
|
|
company=SimpleNamespace(rec_name='Solutema'),
|
|
|
|
|
type='out',
|
|
|
|
|
ncf_number_modified=None,
|
|
|
|
|
ncf_type=None,
|
|
|
|
|
ncf_sequence=None,
|
|
|
|
|
payment_method=None,
|
|
|
|
|
revenue_type=None)
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_prepare_credit_note_from_origin(origin, credit_note)
|
|
|
|
|
finally:
|
|
|
|
|
Invoice._ncf_find_active_sequence = original_find_active_sequence
|
|
|
|
|
Invoice._ncf_electronic_invoicing_enabled = original_enabled
|
|
|
|
|
|
|
|
|
|
self.assertEqual(credit_note.ncf_number_modified, 'B0100000001')
|
|
|
|
|
self.assertEqual(credit_note.ncf_type, '34')
|
|
|
|
|
self.assertEqual(credit_note.ncf_sequence, electronic_sequence)
|
|
|
|
|
self.assertEqual(credit_note.payment_method, '06')
|
|
|
|
|
|
|
|
|
|
def test_modified_ncf_validation_applies_to_debit_notes(self):
|
|
|
|
|
debit_note = SimpleNamespace(
|
|
|
|
|
ncf_type='3',
|
|
|
|
|
ncf_number_modified='B0100000001',
|
|
|
|
|
type='out')
|
|
|
|
|
|
|
|
|
|
Invoice.check_ncf_number_modified(debit_note)
|
|
|
|
|
|
|
|
|
|
def test_fiscal_classification_validation_order_for_customer_invoice(self):
|
|
|
|
|
calls = []
|
|
|
|
|
invoice = SimpleNamespace(
|
|
|
|
|
type='out',
|
|
|
|
|
check_revenue_type=lambda: calls.append('revenue_type'),
|
|
|
|
|
check_expense_type=lambda: calls.append('expense_type'),
|
|
|
|
|
check_isr_withholding_type=lambda: calls.append(
|
|
|
|
|
'isr_withholding_type'),
|
|
|
|
|
check_payment_method=lambda: calls.append('payment_method'))
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_check_fiscal_classification(invoice)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(calls, [
|
|
|
|
|
'revenue_type',
|
|
|
|
|
'isr_withholding_type',
|
|
|
|
|
'payment_method',
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
def test_fiscal_classification_validation_order_for_supplier_invoice(self):
|
|
|
|
|
calls = []
|
|
|
|
|
invoice = SimpleNamespace(
|
|
|
|
|
type='in',
|
|
|
|
|
check_revenue_type=lambda: calls.append('revenue_type'),
|
|
|
|
|
check_expense_type=lambda: calls.append('expense_type'),
|
|
|
|
|
check_isr_withholding_type=lambda: calls.append(
|
|
|
|
|
'isr_withholding_type'),
|
|
|
|
|
check_payment_method=lambda: calls.append('payment_method'))
|
|
|
|
|
|
|
|
|
|
Invoice._ncf_check_fiscal_classification(invoice)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(calls, [
|
|
|
|
|
'expense_type',
|
|
|
|
|
'isr_withholding_type',
|
|
|
|
|
'payment_method',
|
|
|
|
|
])
|