Unify import process.

This commit refs #28045
This commit is contained in:
Sergio Morillo 2023-08-31 22:23:40 +02:00
parent e1d0c4cdfb
commit 9796367b1e
6 changed files with 165 additions and 58 deletions

View File

@ -18,8 +18,9 @@ def register():
edocument.EdocumentTemplate,
edocument.EdocumentExportParams,
edocument.EdocumentExportFile,
edocument.EDocumentImportResult,
party.Party,
party.PartyIdentifier,
party.PartyConfiguration,
stock.Configuration,
stock.ConfigurationSequence,
product.Template,

View File

@ -5,6 +5,7 @@ from trytond.model import ModelSQL, ModelView, fields, Exclude
from sql.conditionals import Coalesce
from sql.operators import Equal as SqlEqual
from trytond.pool import Pool
from trytond.pyson import PYSONEncoder
from trytond.transaction import Transaction
from trytond.i18n import gettext
from trytond.exceptions import UserError
@ -86,11 +87,11 @@ class EdocumentMessage(ModelView, ModelSQL):
default_company = Transaction().context.get('company', None)
vlist = [x.copy() for x in vlist]
for values in vlist:
if config.edocument_sequence:
if not values.get('code') and config.edocument_sequence:
values['code'] = config.get_multivalue(
'edocument_sequence',
company=values.get('company', default_company)).get()
return super(EdocumentMessage, cls).create(vlist)
return super().create(vlist)
class EdocumentMixin(object):
@ -134,25 +135,20 @@ class EdocumentMixin(object):
return message.rec_name
class EdocumentImportMixin(EdocumentMixin):
class EdocumentImportMixin(object):
_edi_message_type = ''
@classmethod
def _get_template_name(cls):
pass
@classmethod
def create_from_edi(cls, edi_info, template):
def create_object_from_edi(cls, edi_content, template):
pass
@classmethod
def postprocess(cls, objects):
pass
@classmethod
def _get_path(cls, message_type):
pool = Pool()
Configuration = pool.get('edocument.configuration.path')
return Configuration._get_path(message_type)
def _postprocess(cls, objects):
return objects
@classmethod
def _template(cls):
@ -165,56 +161,58 @@ class EdocumentImportMixin(EdocumentMixin):
return EdocumentFileManager()
@classmethod
def _create_objects_from_edi(
cls, source_uri, error_uri, template=None, target_model=None):
def _create_objects_from_edi(cls, template=None):
"""
Get objects from edi files
"""
pool = Pool()
if not target_model:
target_model = cls.__name__
Object = pool.get(target_model)
Configuration = pool.get('edocument.configuration.path')
ObjectModel = pool.get(cls.__name__)
Message = pool.get('edocument.message')
paths = Configuration._get_path(cls._edi_message_type)
source_uri, error_uri = paths.path, paths.error_path
if not template:
template = cls._template()
objects = []
records = []
error_files = []
messages = []
imported = []
to_delete = []
manager = cls._get_document_manager()
for name, info in manager._get_messages(source_uri, error_uri).items():
created, errors = cls.create_from_edi(info, template)
if created:
message = Message(code=info)
messages.append(message)
imported.append(name)
for value in created:
if 'id' in value:
new_object = Object(value['id'])
else:
new_object = Object()
for k, v in value.items():
setattr(new_object, k, v)
new_object.message = message
message.origin = new_object
objects.append(new_object)
if imported:
manager._handle_imported(imported)
if errors:
manager._handle_errors(name, errors, error_uri)
Message.save(messages)
Object.save(objects)
return objects
try:
record, errors = cls.create_object_from_edi(info, template)
except RuntimeError:
continue
else:
if errors:
error_files.append(manager._handle_errors(
name, errors, error_uri))
else:
if record:
message = Message(
code=os.path.basename(os.path.splitext(name)[0]),
message=info,
origin=record)
messages.append(message)
records.append(record)
to_delete.append(name)
ObjectModel.save(records)
if messages:
Message.save(messages)
records = cls._postprocess(records)
if to_delete:
manager._handle_imported(to_delete)
return records, error_files
@classmethod
def get_objects_from_edi(cls, message_type, target_model=None):
'''Get objects from edi'''
conf = cls._get_path(message_type)
results = cls._create_objects_from_edi(
conf.path,
conf.error_path,
target_model=target_model)
cls.postprocess(results)
return results
def get_objects_from_edi(cls):
return cls._create_objects_from_edi()
class EdocumentFileManager(object):
@ -222,7 +220,7 @@ class EdocumentFileManager(object):
@classmethod
def _read_file(cls, filename):
with open(filename, encoding='utf-8') as file:
with open(filename, 'r', encoding='cp1252') as file:
return file.read()
@classmethod
@ -240,6 +238,7 @@ class EdocumentFileManager(object):
os.path.splitext(os.path.basename(fname))[0]))
with open(error_fname, 'w') as fp:
fp.write('\n'.join(errors))
return error_fname
@classmethod
def _handle_imported(cls, imported):
@ -247,6 +246,80 @@ class EdocumentFileManager(object):
os.remove(file)
class EDocumentImportResult(ModelView):
"""Import EDIFACT Result"""
__name__ = 'edifact_import.result'
error_file = fields.Binary('Errors', filename='error_filename',
readonly=True)
error_filename = fields.Char('Filename')
message = fields.Text('Message', readonly=True)
def import_edocument_mixin(model_name, result_field):
class ImportEDocumentMixin(object):
start = StateTransition()
errors = StateView('edifact_import.result',
'edocument_edifact.import_result_view_form', [
Button('OK', 'pre_open', 'tryton-ok', default=True),
])
pre_open = StateTransition()
@property
def result_records(self):
return getattr(self.errors, result_field, [])
@result_records.setter
def result_records(self, value):
setattr(self.errors, result_field, [s.id for s in (value or [])])
def transition_start(self):
pool = Pool()
ActiveModel = pool.get(model_name)
Configuration = pool.get('edocument.configuration.path')
paths = Configuration._get_path(ActiveModel._edi_message_type)
results, error_files = ActiveModel.get_objects_from_edi()
self.result_records = results
if error_files:
error_file = os.path.join(paths.error_path, 'error_file')
with open(error_file, 'w') as ef:
for file in error_files:
ef.write('%s:\n' % file.split('/')[-1].split('error_')[-1])
with open(file, 'r') as f:
for line in f:
ef.write('\t- %s' % line)
ef.write('\n')
with open(error_file, mode='r') as f:
self.errors.error_file = f.read()
return 'errors'
return 'pre_open'
def default_errors(self, fields):
return {
'error_file': self.errors.error_file,
'error_filename': 'EDI_error.txt',
'message': self.errors.error_file,
result_field: [r.id for r in self.result_records]
}
def transition_pre_open(self):
return 'open_'
def do_open_(self, action):
if not self.result_records:
return
action['pyson_domain'] = PYSONEncoder().encode([
('id', 'in', [s.id for s in self.result_records])
])
return action, {}
return ImportEDocumentMixin
class EdocumentExportMixin(object):
_message_type = ''

View File

@ -192,5 +192,12 @@
<field name="type">form</field>
<field name="name">export_params_form</field>
</record>
<!-- Import views -->
<record model="ir.ui.view" id="import_result_view_form">
<field name="model">edifact_import.result</field>
<field name="type">form</field>
<field name="name">import_result_form</field>
</record>
</data>
</tryton>

View File

@ -400,4 +400,16 @@ msgstr "Mensajes de Documentación Electrónica"
msgctxt "model:ir.ui.menu,name:menu_edocument_message"
msgid "Messages"
msgstr "Mensajes"
msgstr "Mensajes"
msgctxt "model:edifact_import.result,name:"
msgid "Import EDIFACT Result"
msgstr "Resultado importar EDIFACT"
msgctxt "field:edifact_import.result,error_file:"
msgid "Errors"
msgstr "Errores"
msgctxt "view:edifact_import.result:"
msgid "The import of EDI files has encountered the following errors:"
msgstr "La importación de ficheros EDI ha encontrado los siguientes errores:"

View File

@ -29,15 +29,16 @@ class Party(metaclass=PoolMeta):
], 'Assigned Code')
class PartyIdentifier(metaclass=PoolMeta):
__name__ = 'party.identifier'
class PartyConfiguration(metaclass=PoolMeta):
__name__ = 'party.configuration'
@classmethod
def get_types(cls):
return super().get_types() + [
def __setup__(cls):
super().__setup__()
cls.identifier_types.selection.extend([
('EDI_sender', 'EDI Sender'),
('EDI_receiver', 'EDI Receiver'),
('EDI_supplier', 'EDI Supplier'),
('EDI_payer', 'EDI Payer'),
('EDI_buyer', 'EDI Buyer'),
('EDI_invoice', 'EDI Invoice')]
('EDI_invoice', 'EDI Invoice')])

View File

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<form col="2">
<image name="tryton-warning" xexpand="0" xfill="0"/>
<label string="The import of EDI files has encountered the following errors:"
id="process" yalign="0.5" xalign="0.0" xexpand="1"/>
<newline/>
<label name="error_file"/>
<field name="error_file" filename="error_filename"/>
<field name="message" colspan="2"/>
<field name="error_filename" invisible="1" colspan="2"/>
</form>