From 65b70bee53c6570f312e6f3a138e0c9bcdbee095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Arturo=20Garci=CC=81a?= Date: Sun, 16 Aug 2026 14:17:20 -0400 Subject: [PATCH] Treat DGII authorizations as independent imports --- README.rst | 6 ++++-- importer.py | 39 +++++++++++++++------------------------ tests/test_module.py | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/README.rst b/README.rst index 8cd3137..75affed 100644 --- a/README.rst +++ b/README.rst @@ -49,8 +49,10 @@ Importing DGII authorizations Use **NCF Manager → Import DGII Authorization** to load an authorization downloaded from the DGII Virtual Office. XML, CSV and the HTML table exported with an ``.xls`` extension are supported and detected from their content. -The importer groups lines by ``NUM_SOL`` and identifies each authorization by -``NUM_AUTOR``; file names are not used as fiscal identifiers. It validates +The importer creates an independent workflow record for every ``NUM_AUTOR``. +The same ``NUM_SOL`` may therefore appear in several records without modifying +an authorization that is already active; file names are not used as fiscal +identifiers. It validates approval status, company name, NCF type, prefix, range and approved quantity, and stores the original file, SHA-256, user and import date for audit. diff --git a/importer.py b/importer.py index 551b8c9..122afb8 100644 --- a/importer.py +++ b/importer.py @@ -232,24 +232,6 @@ def import_dgii_authorizations(company, data, filename, activate=False): managers_to_activate = [] imported_lines = [] for row in normalized_rows: - managers = Manager.search([ - ('company', '=', company.id), - ('app_number', '=', row['application_number']), - ], limit=1) - if managers: - manager = managers[0] - else: - manager, = Manager.create([{ - 'company': company.id, - 'app_number': row['application_number'], - 'app_date': row['application_date'].date(), - 'source_filename': filename, - 'source_hash': file_hash, - 'source_file': data, - 'imported_by': Transaction().user, - 'imported_at': datetime.datetime.now(), - }]) - duplicates = Line.search([ ('pos.company', '=', company.id), ('auth_number', '=', row['authorization_number']), @@ -260,10 +242,20 @@ def import_dgii_authorizations(company, data, filename, activate=False): 'ncf_manager.msg_dgii_import_conflict', authorization=row['authorization_number'])) continue - if manager.state != 'draft': - raise UserError(gettext( - 'ncf_manager.msg_dgii_import_closed_request', - request=manager.app_number)) + + # A DGII request number may appear in more than one downloaded + # authorization. Keep every NUM_AUTOR in its own workflow record so + # importing a later authorization never mutates an active one. + manager, = Manager.create([{ + 'company': company.id, + 'app_number': row['application_number'], + 'app_date': row['application_date'].date(), + 'source_filename': filename, + 'source_hash': file_hash, + 'source_file': data, + 'imported_by': Transaction().user, + 'imported_at': datetime.datetime.now(), + }]) line, = Line.create([{ 'pos': manager.id, 'auth_number': row['authorization_number'], @@ -288,8 +280,7 @@ def import_dgii_authorizations(company, data, filename, activate=False): 'imported_at': datetime.datetime.now(), }]) imported_lines.append(line) - if manager not in managers_to_activate: - managers_to_activate.append(manager) + managers_to_activate.append(manager) if activate and managers_to_activate: Manager.activate(managers_to_activate) diff --git a/tests/test_module.py b/tests/test_module.py index af17586..9f28c59 100644 --- a/tests/test_module.py +++ b/tests/test_module.py @@ -313,6 +313,46 @@ class NcfManagerTestCase(ModuleTestCase): self.assertEqual(Manager.search_count([ ('app_number', '=', '6009912073')]), 1) + @with_transaction() + def test_import_new_authorization_for_active_request(self): + 'A new NUM_AUTOR may reuse NUM_SOL without reopening the active one' + pool = Pool() + Manager = pool.get('ncf.manager') + Line = pool.get('ncf.manager.sequence') + company = self._create_company() + + first_data = self._dgii_xml() + first_managers, _ = import_dgii_authorizations( + company, first_data, 'authorization-31.xml', activate=True) + first_manager, = first_managers + self.assertEqual(Manager(first_manager.id).state, 'active') + + second_data = self._dgii_xml( + ncf_type='34', authorization='6005423852', + start='E340000000001', end='E340000001000', quantity='1000') + second_managers, second_lines = import_dgii_authorizations( + company, second_data, 'authorization-34.xml') + + self.assertEqual(len(second_managers), 1) + self.assertEqual(len(second_lines), 1) + self.assertNotEqual(second_managers[0].id, first_manager.id) + self.assertEqual(second_managers[0].state, 'draft') + self.assertEqual(second_lines[0].auth_number, '6005423852') + self.assertEqual(Manager(first_manager.id).state, 'active') + self.assertEqual(Manager.search_count([ + ('company', '=', company.id), + ('app_number', '=', '6009912073'), + ]), 2) + self.assertEqual(Line.search_count([ + ('pos.company', '=', company.id), + ('auth_number', 'in', ['6005423851', '6005423852']), + ]), 2) + + managers, lines = import_dgii_authorizations( + company, second_data, 'authorization-34-again.xml') + self.assertEqual(managers, []) + self.assertEqual(lines, []) + del ModuleTestCase