Prepare account invoice DO for Tryton 8.0

This commit is contained in:
José Arturo García
2026-07-22 22:29:04 -04:00
commit 8035d741fc
26 changed files with 2033 additions and 0 deletions
View File
+85
View File
@@ -0,0 +1,85 @@
from datetime import date
from decimal import Decimal
from types import SimpleNamespace
import unittest
from dateutil.relativedelta import relativedelta
from trytond.modules.account_invoice_do.cron import _build_error_message
from trytond.modules.account_invoice_do.invoice import Invoice, InvoiceLine
class AccountInvoiceDoUnitTestCase(unittest.TestCase):
class Currency:
def round(self, amount):
return amount.quantize(Decimal('0.01'))
def test_due_date_from_payment_term(self):
invoice = SimpleNamespace()
invoice.payment_term = SimpleNamespace(lines=[
SimpleNamespace(relativedeltas=[
relativedelta(months=1, days=5),
]),
])
invoice.invoice_date = date(2026, 1, 10)
self.assertEqual(
Invoice.get_remainder_time(invoice, 'due_date'),
date(2026, 2, 15))
def test_amount_paid_only_for_posted_or_paid_invoices(self):
posted = SimpleNamespace(
id=1, state='posted', total_amount=Decimal('118.00'),
amount_to_pay=Decimal('18.00'), currency=self.Currency())
draft = SimpleNamespace(
id=2, state='draft', total_amount=Decimal('118.00'),
amount_to_pay=Decimal('0.00'), currency=self.Currency())
self.assertEqual(Invoice.get_amount_paid([posted, draft], 'amount_paid'), {
1: Decimal('100.00'),
2: Decimal('0.00'),
})
def test_tax_kind_amount_and_line_total(self):
line = SimpleNamespace(
id=1,
type='line',
amount=Decimal('100.00'),
taxes=[
SimpleNamespace(tax_kind='itbis', rate=Decimal('0.18')),
SimpleNamespace(tax_kind='tip', rate=Decimal('0.10')),
],
currency=self.Currency())
self.assertEqual(
InvoiceLine._compute_tax_kind_amount(line, 'itbis'),
Decimal('18.00'))
self.assertEqual(
InvoiceLine.on_change_with_itbis_invoiced_line(line),
Decimal('18.00'))
self.assertEqual(
InvoiceLine.on_change_with_itbis_line(line),
Decimal('18.00'))
self.assertEqual(
InvoiceLine._compute_line_total_amount(line),
Decimal('128.00'))
def test_subtotal_resets_after_previous_subtotal(self):
invoice = SimpleNamespace()
line1 = SimpleNamespace(
type='line', amount=Decimal('100.00'), taxes=[], currency=None)
subtotal1 = SimpleNamespace(
id=1, type='subtotal', invoice=invoice, currency=None)
line2 = SimpleNamespace(
type='line', amount=Decimal('50.00'), taxes=[], currency=None)
subtotal2 = SimpleNamespace(
id=2, type='subtotal', invoice=invoice, currency=None)
invoice.lines = [line1, subtotal1, line2, subtotal2]
self.assertEqual(
InvoiceLine._compute_line_total_amount(subtotal2),
Decimal('50.00'))
def test_cron_error_message_uses_fallbacks(self):
inv = SimpleNamespace(id=10)
message = _build_error_message(inv, ValueError('boom'))
self.assertIn('ID: 10', message)
self.assertIn('Numero: N/D', message)
self.assertIn('Error: boom', message)
+153
View File
@@ -0,0 +1,153 @@
import datetime
from decimal import Decimal
from types import SimpleNamespace
import unittest
from trytond.modules.account.tests.test_module import (
create_chart, get_fiscalyear)
from trytond.modules.account_invoice_do.invoice import InvoiceLine
from trytond.modules.company.tests import create_company, set_company
from trytond.pool import Pool
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
class AccountInvoiceDoTestCase(ModuleTestCase):
"Test Account Invoice Do module"
module = 'account_invoice_do'
@with_transaction()
def test_customer_invoice_without_product_posts_and_computes_do_fields(self):
'Post customer invoice and compute Dominican invoice helper fields'
pool = Pool()
Account = pool.get('account.account')
FiscalYear = pool.get('account.fiscalyear')
InvoiceSequence = pool.get('account.fiscalyear.invoice_sequence')
Invoice = pool.get('account.invoice')
Journal = pool.get('account.journal')
Party = pool.get('party.party')
PaymentTerm = pool.get('account.invoice.payment_term')
Sequence = pool.get('ir.sequence.strict')
SequenceType = pool.get('ir.sequence.type')
today = datetime.date.today()
company = create_company()
create_chart(company)
fiscalyear = get_fiscalyear(company, today=today)
sequence_type, = SequenceType.search([
('name', '=', 'Invoice'),
], limit=1)
invoice_sequence, = Sequence.create([{
'name': fiscalyear.name,
'sequence_type': sequence_type.id,
'company': company.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])
receivable, = Account.search([
('company', '=', company.id),
('type.receivable', '=', True),
('party_required', '=', True),
], limit=1)
revenue, = Account.search([
('company', '=', company.id),
('type.revenue', '=', True),
('closed', '!=', True),
], limit=1)
journal, = Journal.search([('type', '=', 'revenue')], limit=1)
party, = Party.create([{
'name': 'Cliente local',
'addresses': [('create', [{}])],
}])
term, = PaymentTerm.create([{
'name': 'Contado',
'lines': [('create', [{'type': 'remainder'}])],
}])
with set_company(company):
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': term.id,
'lines': [('create', [{
'type': 'line',
'description': 'Servicio local',
'quantity': 2,
'unit_price': Decimal('150.00'),
'account': revenue.id,
}])],
}])
Invoice.post([invoice])
invoice = Invoice(invoice.id)
self.assertEqual(invoice.state, 'posted')
self.assertEqual(invoice.untaxed_amount, Decimal('300.00'))
self.assertEqual(invoice.total_amount, Decimal('300.00'))
line, = invoice.lines
self.assertEqual(line.product_type, '')
self.assertEqual(line.itbis_invoiced_line, Decimal('0.00'))
self.assertEqual(line.itbis_line, Decimal('0.00'))
self.assertEqual(line.line_total, Decimal('300.00'))
del ModuleTestCase
class AccountInvoiceDoUnitTestCase(unittest.TestCase):
def _currency(self):
return SimpleNamespace(round=lambda amount: amount.quantize(
Decimal('0.01')))
def _tax(self, kind, rate):
return SimpleNamespace(tax_kind=kind, rate=Decimal(rate))
def _line(self, **values):
defaults = {
'id': 1,
'type': 'line',
'product': None,
'taxes': [],
'currency': self._currency(),
'amount': Decimal('100.00'),
}
defaults.update(values)
return SimpleNamespace(**defaults)
def test_product_type_is_empty_without_product(self):
line = self._line()
self.assertEqual(InvoiceLine.on_change_with_product_type(line), '')
def test_tax_kind_amounts_are_computed_from_line_base(self):
line = self._line(taxes=[
self._tax('itbis', '0.18'),
self._tax('isc', '0.10'),
])
self.assertEqual(
InvoiceLine._compute_tax_kind_amount(line, 'itbis'),
Decimal('18.00'))
self.assertEqual(
InvoiceLine._compute_tax_kind_amount(line, 'isc'),
Decimal('10.00'))
def test_line_total_includes_all_line_taxes(self):
line = self._line(taxes=[
self._tax('itbis', '0.18'),
self._tax('cdt', '0.02'),
])
self.assertEqual(
InvoiceLine._compute_line_total_amount(line),
Decimal('120.00'))