Fix NCF overlap validation by document direction
Publicar paquete PyPI / publish (push) Successful in 1m48s
Publicar paquete PyPI / publish (push) Successful in 1m48s
This commit is contained in:
+5
-2
@@ -37,8 +37,11 @@ Finished``. Create the authorization and its fiscal lines in draft, then use
|
|||||||
the **Activate** button. A line can select an existing strict sequence or ask
|
the **Activate** button. A line can select an existing strict sequence or ask
|
||||||
the module to create one on activation from its authorized range. Activation
|
the module to create one on activation from its authorized range. Activation
|
||||||
checks company, fiscal type, prefix, padding, validity, availability and range
|
checks company, fiscal type, prefix, padding, validity, availability and range
|
||||||
overlap. The last issued number automatically finishes the line. Finishing
|
overlap. Incoming supplier documents and outgoing customer documents use
|
||||||
an authorization closes every remaining active line without reusing numbers.
|
independent numbering authorities, so overlap is enforced only within the
|
||||||
|
same document direction. The last issued number automatically finishes the
|
||||||
|
line. Finishing an authorization closes every remaining active line without
|
||||||
|
reusing numbers.
|
||||||
|
|
||||||
Electronic fiscal numbers are only reserved by this module. Activating an
|
Electronic fiscal numbers are only reserved by this module. Activating an
|
||||||
E-series authorization never signs or transmits an e-CF to DGII.
|
E-series authorization never signs or transmits an e-CF to DGII.
|
||||||
|
|||||||
@@ -568,6 +568,7 @@ class NCFManagerSequences(Workflow, ModelSQL, ModelView):
|
|||||||
('id', '!=', self.id),
|
('id', '!=', self.id),
|
||||||
('pos.company', '=', self.pos.company.id),
|
('pos.company', '=', self.pos.company.id),
|
||||||
('ncf_type', '=', self.ncf_type),
|
('ncf_type', '=', self.ncf_type),
|
||||||
|
('invoice_type', '=', self.invoice_type),
|
||||||
('state', '=', 'active'),
|
('state', '=', 'active'),
|
||||||
('ncf_sequences', '!=', None),
|
('ncf_sequences', '!=', None),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -165,6 +165,46 @@ class NcfManagerTestCase(ModuleTestCase):
|
|||||||
}])
|
}])
|
||||||
return sequence
|
return sequence
|
||||||
|
|
||||||
|
def _create_active_e31_range(self, company, invoice_type,
|
||||||
|
from_number=1, until_number=100):
|
||||||
|
pool = Pool()
|
||||||
|
Manager = pool.get('ncf.manager')
|
||||||
|
ManagerSequence = pool.get('ncf.manager.sequence')
|
||||||
|
ModelData = pool.get('ir.model.data')
|
||||||
|
StrictSequence = pool.get('ir.sequence.strict')
|
||||||
|
SequenceType = pool.get('ir.sequence.type')
|
||||||
|
today = datetime.date.today()
|
||||||
|
|
||||||
|
sequence_type = SequenceType(ModelData.get_id(
|
||||||
|
'ncf_manager', 'sequence_type_out_invoice_31'))
|
||||||
|
strict_sequence, = StrictSequence.create([{
|
||||||
|
'name': f'E31 {invoice_type}',
|
||||||
|
'sequence_type': sequence_type.id,
|
||||||
|
'company': company.id,
|
||||||
|
'prefix': 'E31',
|
||||||
|
'padding': 10,
|
||||||
|
'number_next': from_number,
|
||||||
|
'number_increment': 1,
|
||||||
|
'from_number': from_number,
|
||||||
|
'until_number': until_number,
|
||||||
|
'expiration_date': datetime.date(today.year + 1, 12, 31),
|
||||||
|
}])
|
||||||
|
manager, = Manager.create([{
|
||||||
|
'company': company.id,
|
||||||
|
'app_date': today,
|
||||||
|
'app_number': 'APP0000001',
|
||||||
|
'auth_number': 'AUT0000001',
|
||||||
|
'state': 'active',
|
||||||
|
}])
|
||||||
|
line, = ManagerSequence.create([{
|
||||||
|
'pos': manager.id,
|
||||||
|
'ncf_type': '31',
|
||||||
|
'ncf_sequences': strict_sequence.id,
|
||||||
|
'invoice_type': invoice_type,
|
||||||
|
'state': 'active',
|
||||||
|
}])
|
||||||
|
return line
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _dgii_xml(ncf_type='31', authorization='6005423851',
|
def _dgii_xml(ncf_type='31', authorization='6005423851',
|
||||||
start='E310000000001', end='E310000000100', quantity='100'):
|
start='E310000000001', end='E310000000100', quantity='100'):
|
||||||
@@ -292,6 +332,70 @@ class NcfManagerTestCase(ModuleTestCase):
|
|||||||
self.assertEqual(manager.ncf_sequences[0].state, 'finished')
|
self.assertEqual(manager.ncf_sequences[0].state, 'finished')
|
||||||
self.assertIsNotNone(manager.finished_at)
|
self.assertIsNotNone(manager.finished_at)
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_overlap_is_independent_by_invoice_direction(self):
|
||||||
|
'A supplier range must not block the company outgoing authorization'
|
||||||
|
pool = Pool()
|
||||||
|
Manager = pool.get('ncf.manager')
|
||||||
|
company = self._create_company()
|
||||||
|
today = datetime.date.today()
|
||||||
|
|
||||||
|
supplier_line = self._create_active_e31_range(
|
||||||
|
company, 'invoice_supplier', until_number=2_000_000_000)
|
||||||
|
manager, = Manager.create([{
|
||||||
|
'company': company.id,
|
||||||
|
'app_date': today,
|
||||||
|
'app_number': '6009912073',
|
||||||
|
'auth_number': '6005423851',
|
||||||
|
'ncf_sequences': [('create', [{
|
||||||
|
'invoice_type': 'invoice_customer',
|
||||||
|
'ncf_type': '31',
|
||||||
|
'sequence_mode': 'create',
|
||||||
|
'from_number': 1,
|
||||||
|
'number_next': 1,
|
||||||
|
'until_number': 100,
|
||||||
|
'expiration_date': datetime.date(
|
||||||
|
today.year + 1, 12, 31),
|
||||||
|
}])],
|
||||||
|
}])
|
||||||
|
|
||||||
|
Manager.activate([manager])
|
||||||
|
|
||||||
|
manager = Manager(manager.id)
|
||||||
|
self.assertEqual(manager.state, 'active')
|
||||||
|
self.assertEqual(manager.ncf_sequences[0].state, 'active')
|
||||||
|
self.assertEqual(supplier_line.state, 'active')
|
||||||
|
|
||||||
|
@with_transaction()
|
||||||
|
def test_overlap_still_blocks_same_invoice_direction(self):
|
||||||
|
'Two outgoing authorizations may not reserve the same E31 numbers'
|
||||||
|
pool = Pool()
|
||||||
|
Manager = pool.get('ncf.manager')
|
||||||
|
company = self._create_company()
|
||||||
|
today = datetime.date.today()
|
||||||
|
|
||||||
|
self._create_active_e31_range(
|
||||||
|
company, 'invoice_customer', from_number=1, until_number=100)
|
||||||
|
manager, = Manager.create([{
|
||||||
|
'company': company.id,
|
||||||
|
'app_date': today,
|
||||||
|
'app_number': '6009912073',
|
||||||
|
'auth_number': '6005423851',
|
||||||
|
'ncf_sequences': [('create', [{
|
||||||
|
'invoice_type': 'invoice_customer',
|
||||||
|
'ncf_type': '31',
|
||||||
|
'sequence_mode': 'create',
|
||||||
|
'from_number': 50,
|
||||||
|
'number_next': 50,
|
||||||
|
'until_number': 150,
|
||||||
|
'expiration_date': datetime.date(
|
||||||
|
today.year + 1, 12, 31),
|
||||||
|
}])],
|
||||||
|
}])
|
||||||
|
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
Manager.activate([manager])
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_import_dgii_authorization_is_idempotent(self):
|
def test_import_dgii_authorization_is_idempotent(self):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
[tryton]
|
[tryton]
|
||||||
version=8.0.1
|
version=8.0.2
|
||||||
depends:
|
depends:
|
||||||
account_do
|
account_do
|
||||||
account_invoice_do
|
account_invoice_do
|
||||||
|
|||||||
Reference in New Issue
Block a user