parent
6c8f2dff5b
commit
e1d0c4cdfb
|
@ -16,6 +16,8 @@ def register():
|
|||
configuration.ConfigurationPath,
|
||||
edocument.EdocumentMessage,
|
||||
edocument.EdocumentTemplate,
|
||||
edocument.EdocumentExportParams,
|
||||
edocument.EdocumentExportFile,
|
||||
party.Party,
|
||||
party.PartyIdentifier,
|
||||
stock.Configuration,
|
||||
|
|
132
edocument.py
132
edocument.py
|
@ -8,10 +8,12 @@ from trytond.pool import Pool
|
|||
from trytond.transaction import Transaction
|
||||
from trytond.i18n import gettext
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.wizard import StateTransition, StateView, Button
|
||||
from genshi.template import TextTemplate
|
||||
from io import open
|
||||
import oyaml as yaml
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
|
||||
KNOWN_EXTENSIONS = ['.txt', '.edi', '.pla']
|
||||
|
@ -55,10 +57,9 @@ class EdocumentMessage(ModelView, ModelSQL):
|
|||
"""EDIFACT message"""
|
||||
__name__ = 'edocument.message'
|
||||
|
||||
code = fields.Char('Code')
|
||||
message = fields.Text('Message')
|
||||
sequence = fields.Many2One('ir.sequence', 'Sequence')
|
||||
origin = fields.Reference('Origin', selection='get_origin')
|
||||
code = fields.Char('Code', readonly=True)
|
||||
message = fields.Text('Message', readonly=True)
|
||||
origin = fields.Reference('Origin', selection='get_origin', readonly=True)
|
||||
|
||||
def get_rec_name(self, name):
|
||||
return 'EW' + '{0:0>6}'.format(self.code)
|
||||
|
@ -94,25 +95,27 @@ class EdocumentMessage(ModelView, ModelSQL):
|
|||
|
||||
class EdocumentMixin(object):
|
||||
|
||||
messages = fields.One2Many('edocument.message', 'origin', 'Message')
|
||||
edocument_processed = fields.Function(
|
||||
fields.Boolean('Processed'), 'get_edocument_processed',
|
||||
searcher='search_edocument_processed')
|
||||
edi_messages = fields.One2Many('edocument.message', 'origin',
|
||||
'EDI Messages')
|
||||
edi_processed = fields.Function(
|
||||
fields.Boolean('EDI Processed'), 'get_edi_processed',
|
||||
searcher='search_edi_processed')
|
||||
edi_message = fields.Function(
|
||||
fields.Char('EDI Message'), 'get_edi_message')
|
||||
|
||||
def get_edocument_processed(self, name=None):
|
||||
return len(self.messages) > 0
|
||||
def get_edi_processed(self, name=None):
|
||||
return bool(self.edi_messages)
|
||||
|
||||
@classmethod
|
||||
def search_edocument_processed(cls, name, clause):
|
||||
def search_edi_processed(cls, name, clause):
|
||||
exist = {
|
||||
True: [('messages', '=', None)],
|
||||
False: [('messages', '!=', None)]}
|
||||
True: [('edi_messages', '=', None)],
|
||||
False: [('edi_messages', '!=', None)]
|
||||
}
|
||||
return exist[bool(clause[1] == '=') ^ bool(clause[2])]
|
||||
|
||||
def get_edi_message(self, name=None):
|
||||
return self.messages[-1].rec_name if self.messages else ''
|
||||
return self.edi_messages[-1].rec_name if self.edi_messages else ''
|
||||
|
||||
@classmethod
|
||||
def copy(cls, records, default=None):
|
||||
|
@ -120,9 +123,16 @@ class EdocumentMixin(object):
|
|||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
default['messages'] = None
|
||||
default['edi_messages'] = None
|
||||
return super().copy(records, default=default)
|
||||
|
||||
@property
|
||||
def edi_party(self):
|
||||
return self.party
|
||||
|
||||
def _get_edi_message_key(self, message):
|
||||
return message.rec_name
|
||||
|
||||
|
||||
class EdocumentImportMixin(EdocumentMixin):
|
||||
|
||||
|
@ -238,32 +248,53 @@ class EdocumentFileManager(object):
|
|||
|
||||
|
||||
class EdocumentExportMixin(object):
|
||||
_message_type = ''
|
||||
|
||||
def _default_template_path(self, message_type):
|
||||
return os.path.join(os.path.dirname(__file__),
|
||||
'template', message_type.lower() + '.txt')
|
||||
start = StateTransition()
|
||||
params = StateView('edifact_export.params',
|
||||
'edocument_edifact.export_params_view_form',
|
||||
[
|
||||
Button('Cancel', 'end', 'tryton-cancel'),
|
||||
Button('Export', 'show_file', 'tryton-forward')
|
||||
])
|
||||
show_file = StateView('edifact_export.file',
|
||||
'edocument_edifact.export_file_view_form', [
|
||||
Button('OK', 'end', 'tryton-ok')
|
||||
])
|
||||
|
||||
def transition_start(self):
|
||||
return 'params'
|
||||
|
||||
@classmethod
|
||||
def _default_template_path_file(cls):
|
||||
pass
|
||||
|
||||
def _default_template_path(self):
|
||||
return os.path.join(os.path.dirname(
|
||||
self._default_template_path_file()),
|
||||
'template',
|
||||
self._message_type.lower() + '.txt')
|
||||
|
||||
def _write_file(self, file_path, file, encoding='utf-8'):
|
||||
edi_file = open(file_path, 'w+', encoding=encoding)
|
||||
edi_file.write(file)
|
||||
edi_file.close()
|
||||
with open(file_path, 'w+', encoding=encoding) as edi_file:
|
||||
edi_file.write(file)
|
||||
|
||||
def _edi_template(self, message_type, party):
|
||||
def _edi_template(self, party):
|
||||
pool = Pool()
|
||||
EdocumentTemplate = pool.get('edocument.template')
|
||||
|
||||
templates = EdocumentTemplate.search([
|
||||
('message_type', '=', message_type),
|
||||
('message_type', '=', self._message_type),
|
||||
('party', '=', party)])
|
||||
if templates:
|
||||
return templates[0].template, templates[0].encoding
|
||||
else:
|
||||
template_path = self._default_template_path(message_type)
|
||||
template_path = self._default_template_path()
|
||||
with open(template_path) as file:
|
||||
template = file.read()
|
||||
return template, 'utf-8'
|
||||
|
||||
def generate_message(self, message_type, export_again=False):
|
||||
def generate_message(self, export_again=False):
|
||||
pool = Pool()
|
||||
ActiveModel = self.model
|
||||
Message = pool.get('edocument.message')
|
||||
|
@ -271,7 +302,7 @@ class EdocumentExportMixin(object):
|
|||
|
||||
domain = [('id', 'in', Transaction().context['active_ids'])]
|
||||
if not export_again:
|
||||
domain.append(('edocument_processed', '=', False))
|
||||
domain.append(('edi_processed', '=', False))
|
||||
|
||||
records = ActiveModel.search(domain)
|
||||
if not records:
|
||||
|
@ -280,13 +311,18 @@ class EdocumentExportMixin(object):
|
|||
companies = set(x.company for x in records)
|
||||
if len(companies) > 1:
|
||||
raise UserError(gettext('edocument_edifact.msg_company_unique'))
|
||||
|
||||
company, = companies
|
||||
edifact_sender = [x for x in company.party.identifiers
|
||||
if x.type == 'EDI_sender']
|
||||
if not edifact_sender:
|
||||
raise UserError(gettext('edocument_edifact.msg_EDI_sender',
|
||||
company=company.party.name))
|
||||
parties = set(x.party for x in records)
|
||||
parties = set(x.edi_party for x in records)
|
||||
if len(parties) > 1:
|
||||
raise UserError(
|
||||
gettext('edocument_edifact.msg_party_receiver_unique'))
|
||||
|
||||
party, = parties
|
||||
edifact_receiver = [x for x in party.identifiers
|
||||
if x.type == 'EDI_receiver']
|
||||
|
@ -294,7 +330,7 @@ class EdocumentExportMixin(object):
|
|||
raise UserError(gettext('edocument_edifact.msg_party_EDI_receiver',
|
||||
party=party.name))
|
||||
|
||||
template, encoding = self._edi_template(message_type, party)
|
||||
template, encoding = self._edi_template(party)
|
||||
loader = TextTemplate(template)
|
||||
for record in records:
|
||||
message = Message()
|
||||
|
@ -304,16 +340,15 @@ class EdocumentExportMixin(object):
|
|||
"message": message,
|
||||
"sender": edifact_sender[0].code,
|
||||
"receiver": edifact_receiver[0].code,
|
||||
"records": [[message.code, record]],
|
||||
"records": [[record._get_edi_message_key(message), record]],
|
||||
"date": message.create_date.strftime("%y%m%d"),
|
||||
"time": message.create_date.strftime("%H%M")
|
||||
}
|
||||
message.message = loader.generate(
|
||||
data=data, items=[1, 2, 3]).render()
|
||||
message.save()
|
||||
record.save()
|
||||
|
||||
conf = Configuration._get_path(message_type)
|
||||
conf = Configuration._get_path(self._message_type)
|
||||
chars = ['.', ' ', '-', ':']
|
||||
f_name = ''.join(
|
||||
[c for c in str(datetime.now()) if c not in chars])
|
||||
|
@ -322,4 +357,37 @@ class EdocumentExportMixin(object):
|
|||
self._write_file(file_name, message.message, encoding=encoding)
|
||||
if not message.code:
|
||||
raise UserError(gettext('edocument_edifact.msg_EDI_sequence'))
|
||||
return message.message, message_type + message.code + '.EDI'
|
||||
return message.message, self._message_type + message.code + '.EDI'
|
||||
|
||||
def default_show_file(self, fields):
|
||||
if not Transaction().context['active_ids']:
|
||||
return {'file': None, 'file_name': None}
|
||||
|
||||
message, edi_file_name = self.generate_message(
|
||||
export_again=self.params.export_again)
|
||||
|
||||
if not message:
|
||||
return {}
|
||||
file_no, file_name = tempfile.mkstemp('.txt', 'tryton_')
|
||||
with open(file_name, 'w+') as file_p:
|
||||
file_p.write(message)
|
||||
file_p.close()
|
||||
with open(file_name, mode='r') as file_p:
|
||||
self.show_file.file = file_p.read()
|
||||
self.show_file.file_name = edi_file_name
|
||||
return {'file': self.show_file.file, 'file_name': edi_file_name}
|
||||
|
||||
|
||||
class EdocumentExportParams(ModelView):
|
||||
'''EDIFACT Export Params'''
|
||||
__name__ = 'edifact_export.params'
|
||||
|
||||
export_again = fields.Boolean('Export Again')
|
||||
|
||||
|
||||
class EdocumentExportFile(ModelView):
|
||||
'''EDIFACT Export File'''
|
||||
__name__ = 'edifact_export.file'
|
||||
|
||||
file = fields.Binary('File', readonly=True)
|
||||
file_name = fields.Char('File Name')
|
||||
|
|
|
@ -135,5 +135,62 @@
|
|||
action="act_edocument_configuration_path"
|
||||
sequence="10" icon="tryton-list"
|
||||
id="menu_edocument_configuration_path"/>
|
||||
|
||||
<!-- Edocument Message -->
|
||||
<record model="ir.ui.view" id="edocument_message_view_form">
|
||||
<field name="model">edocument.message</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">edocument_message_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="edocument_message_view_list">
|
||||
<field name="model">edocument.message</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">edocument_message_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_edocument_message">
|
||||
<field name="name">Edocument Messages</field>
|
||||
<field name="res_model">edocument.message</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_edocument_message_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="edocument_message_view_list"/>
|
||||
<field name="act_window" ref="act_edocument_message"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_edocument_message_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="edocument_message_view_form"/>
|
||||
<field name="act_window" ref="act_edocument_message"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_edocument_message">
|
||||
<field name="model" search="[('model', '=', 'edocument.message')]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_edocument_message_group_group_admin">
|
||||
<field name="model" search="[('model', '=', 'edocument.message')]"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
<menuitem parent="menu_edocument" sequence="20" id="menu_edocument_message" name="Messages"
|
||||
action="act_edocument_message"/>
|
||||
|
||||
<!-- Export views -->
|
||||
<record model="ir.ui.view" id="export_file_view_form">
|
||||
<field name="model">edifact_export.file</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">export_file_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="export_params_view_form">
|
||||
<field name="model">edifact_export.params</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">export_params_form</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
42
locale/es.po
42
locale/es.po
|
@ -26,17 +26,9 @@ msgctxt "model:ir.message,text:msg_EDI_export_path"
|
|||
msgid "EDI export path is not defined in Edocument Configuration."
|
||||
msgstr "Ruta de exportación EDI no está definida en Configuración de Documentación Electrónica."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_customer_unique"
|
||||
msgid "Cannot send invoices for more than 1 customer"
|
||||
msgstr "No se pueden enviar facturas a más de 1 cliente."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_shipment_customer_unique"
|
||||
msgid "Cannot send shipments for more than 1 customer"
|
||||
msgstr "No se pueden enviar albaranes a más de 1 cliente."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_customer_EDI_receiver"
|
||||
msgid "Customer \"%(customer)s\" lacks EDI receiver identifier"
|
||||
msgstr "El cliente \"%(customer)s\" no tiene identificador de receptor EDI."
|
||||
msgctxt "model:ir.message,text:msg_party_receiver_unique"
|
||||
msgid "Cannot send document for more than one Party receiver."
|
||||
msgstr "No se pueden enviar documentos a más de un tercero receptor."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_message_type_unique"
|
||||
msgid "Message type must be unique."
|
||||
|
@ -381,3 +373,31 @@ msgstr "93A"
|
|||
msgctxt "selection:party.party,edi_release_number:"
|
||||
msgid "96A"
|
||||
msgstr "96A"
|
||||
|
||||
msgctxt "field:edifact_export.params,export_again:"
|
||||
msgid "Export Again"
|
||||
msgstr "Exportar de nuevo"
|
||||
|
||||
msgctxt "field:edifact_export.file,file:"
|
||||
msgid "File"
|
||||
msgstr "Fichero"
|
||||
|
||||
msgctxt "field:edifact_export.file,file_name:"
|
||||
msgid "File Name"
|
||||
msgstr "Nombre de archivo"
|
||||
|
||||
msgctxt "model:edifact_export.params,name:"
|
||||
msgid "EDIFACT Export Params"
|
||||
msgstr "Parámetros exportar EDIFACT"
|
||||
|
||||
msgctxt "model:edifact_export.file,name:"
|
||||
msgid "EDIFACT Export File"
|
||||
msgstr "Fichero exportar EDIFACT"
|
||||
|
||||
msgctxt "model:ir.action,name:act_edocument_message"
|
||||
msgid "Edocument Messages"
|
||||
msgstr "Mensajes de Documentación Electrónica"
|
||||
|
||||
msgctxt "model:ir.ui.menu,name:menu_edocument_message"
|
||||
msgid "Messages"
|
||||
msgstr "Mensajes"
|
10
message.xml
10
message.xml
|
@ -6,11 +6,8 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_company_unique">
|
||||
<field name="text">Cannot send invoices from more than 1 company.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_customer_unique">
|
||||
<field name="text">Cannot send invoices for more than 1 customer.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_shipment_customer_unique">
|
||||
<field name="text">Cannot send shipments for more than 1 customer.</field>
|
||||
<record model="ir.message" id="msg_party_receiver_unique">
|
||||
<field name="text">Cannot send document for more than one Party receiver.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_edi_party_message_type">
|
||||
<field name="text">Combination of message type and party must be unique.</field>
|
||||
|
@ -21,9 +18,6 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_party_EDI_receiver">
|
||||
<field name="text">Party "%(party)s" lacks EDI receiver identifier.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_customer_EDI_receiver">
|
||||
<field name="text">Customer "%(customer)s" lacks EDI receiver identifier.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_EDI_sequence">
|
||||
<field name="text">EDI Sequence must be defined in Edocument Configuration.</field>
|
||||
</record>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<form>
|
||||
<label name="code"/>
|
||||
<field name="code"/>
|
||||
<label name="origin"/>
|
||||
<field name="origin"/>
|
||||
<separator name="message" colspan="4"/>
|
||||
<field name="message" colspan="4"/>
|
||||
</form>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<tree>
|
||||
<field name="rec_name"/>
|
||||
<field name="origin" expand="1"/>
|
||||
</tree>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<form>
|
||||
<label name="file"/>
|
||||
<field name="file"/>
|
||||
</form>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<form>
|
||||
<label name="export_again"/>
|
||||
<field name="export_again"/>
|
||||
</form>
|
Loading…
Reference in New Issue