258 lines
9.3 KiB
Python
258 lines
9.3 KiB
Python
# The COPYRIGHT file at the top level of this repository contains the full
|
|
# copyright notices and license terms.
|
|
import os
|
|
from functools import partial
|
|
from trytond.model import fields, ModelSQL, ModelView, DeactivableMixin, Model
|
|
from trytond.pool import Pool
|
|
from trytond.pyson import Eval
|
|
from trytond.transaction import Transaction
|
|
from trytond.modules.company import CompanyReport
|
|
from .load import NoteMixin
|
|
from genshi.template import TextTemplate
|
|
from sql import Literal
|
|
|
|
|
|
file_id = 'cmr_template_image_id'
|
|
store_prefix = None
|
|
|
|
|
|
class CMRTemplate(DeactivableMixin, ModelSQL, ModelView):
|
|
'''CMR Template'''
|
|
__name__ = 'carrier.load.cmr.template'
|
|
|
|
name = fields.Char('Name', required=True)
|
|
lines = fields.One2Many('carrier.load.cmr.template.line', 'template',
|
|
'Lines')
|
|
copy_as_sender = fields.Boolean('Copy with Company as sender',
|
|
help='If checked add a copy on CMR with Company as sender. '
|
|
'Only when Shipment Party defined.')
|
|
|
|
def get_section(self, section):
|
|
for line in self.lines:
|
|
if line.section == section:
|
|
return line
|
|
|
|
def get_section_text(self, section, record=None, lang=None, *args):
|
|
line = self.get_section(section)
|
|
if not line:
|
|
return ''
|
|
if not lang or lang.code == Transaction().context['language']:
|
|
text = line.text
|
|
else:
|
|
with Transaction().set_context(language=lang.code):
|
|
text = line.__class__(line.id).text
|
|
return self.eval(text, record, *(list(args) + [lang]))
|
|
|
|
def get_section_image(self, section):
|
|
line = self.get_section(section)
|
|
if not line or not line.image:
|
|
# use a blank image to avoid failed render icon
|
|
blank = os.path.join(os.path.dirname(__file__), 'images',
|
|
'blank.png')
|
|
with open(blank, 'rb') as fp:
|
|
return fp.read()
|
|
return line.image
|
|
|
|
@classmethod
|
|
def eval(cls, expression, record, *args):
|
|
if not expression:
|
|
return ''
|
|
|
|
template = TextTemplate(expression)
|
|
template_context = cls.template_context(record, *args)
|
|
text = template.generate(**template_context).render()
|
|
return '\n'.join([x.strip() for x in text.splitlines()])
|
|
|
|
@staticmethod
|
|
def template_context(record, *args):
|
|
User = Pool().get('res.user')
|
|
|
|
user = None
|
|
if Transaction().user:
|
|
user = User(Transaction().user)
|
|
res = {
|
|
'record': record,
|
|
'user': user,
|
|
}
|
|
for arg in args:
|
|
if not isinstance(arg, Model):
|
|
continue
|
|
if arg.__name__ == 'party.address':
|
|
res['full_address'] = arg.full_address
|
|
res.update(arg._get_address_substitutions())
|
|
arg = arg.party
|
|
if arg.__name__ == 'party.party':
|
|
res.update({
|
|
'party_full_name': arg.full_name,
|
|
'party_tax_identifier': arg.tax_identifier and
|
|
arg.tax_identifier.code or '',
|
|
})
|
|
if arg.__name__ == 'ir.lang':
|
|
res['lang'] = arg
|
|
return res
|
|
|
|
@staticmethod
|
|
def _get_section_defaults():
|
|
return {
|
|
'1':
|
|
'${party_full_name}\n'
|
|
'${full_address}',
|
|
'2':
|
|
'${party_full_name}\n'
|
|
'${full_address}',
|
|
'3':
|
|
'${full_address}',
|
|
'4':
|
|
'${party_full_name}\n'
|
|
'${city}\n'
|
|
'${subdivision}'
|
|
}
|
|
|
|
@classmethod
|
|
def default_lines(cls):
|
|
return [{'section': k, 'text': v}
|
|
for k, v in cls._get_section_defaults().items()]
|
|
|
|
|
|
class CMRTemplateLine(ModelSQL, ModelView):
|
|
'''CMR Template Line'''
|
|
__name__ = 'carrier.load.cmr.template.line'
|
|
|
|
template = fields.Many2One('carrier.load.cmr.template', 'Template',
|
|
required=True, select=True, ondelete='CASCADE')
|
|
section = fields.Selection([
|
|
('1', '1 - Sender'),
|
|
('1-right', '1 - Sender (Right)'),
|
|
('2', '2 - Consignee'),
|
|
('2-right', '2 - Consignee (Right)'),
|
|
('3', '3 - Place of delivery of the goods'),
|
|
('3-right', '3 - Place of delivery of the goods (Right)'),
|
|
('4', '4 - Place of taking over the goods'),
|
|
('5', '5 - Documents attached'),
|
|
('6-9', '6 to 9 - Bottom notes'),
|
|
('13', '13 - Instructions'),
|
|
('18', '18 - Carrier reservations'),
|
|
('19', '19 - Special agreements'),
|
|
('22', '22 - Signature & stamp of sender'),
|
|
('head-right', 'Header (Right)'),
|
|
('head-left', 'Header (Left)'),
|
|
], 'Section', required=True, sort=False)
|
|
text = fields.Text('Text', translate=True, states={
|
|
'invisible': (Eval('section') == '22'),
|
|
},
|
|
help='Define static text or expression to evaluate with '
|
|
'current load order (eg. ${record.shipment.number})',
|
|
depends=['section'])
|
|
image = fields.Binary('Image', file_id='image_id',
|
|
store_prefix=store_prefix, states={
|
|
'invisible': (Eval('section') != '22'),
|
|
'required': (Eval('section') == '22')
|
|
},
|
|
depends=['section'])
|
|
image_id = fields.Char('Image ID', readonly=True)
|
|
|
|
@fields.depends('section', 'text')
|
|
def on_change_section(self):
|
|
Template = Pool().get('carrier.load.cmr.template')
|
|
defaults = Template._get_section_defaults()
|
|
if self.section in defaults and not self.text:
|
|
self.text = defaults[self.section]
|
|
|
|
@classmethod
|
|
def __register__(cls, module_name):
|
|
cursor = Transaction().connection.cursor()
|
|
Template = Pool().get('carrier.load.cmr.template')
|
|
table = cls.__table__()
|
|
template = Template.__table__()
|
|
|
|
super().__register__(module_name)
|
|
|
|
# backward compatibility
|
|
for section, text in Template._get_section_defaults().items():
|
|
cursor.execute(*table.select(
|
|
table.id,
|
|
where=(table.section == section)))
|
|
if not cursor.fetchone():
|
|
cursor.execute(*table.insert([
|
|
table.create_uid,
|
|
table.write_uid,
|
|
table.create_date,
|
|
table.write_date,
|
|
table.template,
|
|
table.section,
|
|
table.text
|
|
],
|
|
template.select(
|
|
template.create_uid,
|
|
template.write_uid,
|
|
template.create_date,
|
|
template.write_date,
|
|
template.id,
|
|
Literal(section),
|
|
Literal(text))
|
|
)
|
|
)
|
|
|
|
|
|
class CMR(NoteMixin, CompanyReport):
|
|
"""CMR report"""
|
|
__name__ = 'carrier.load.order.cmr'
|
|
|
|
@classmethod
|
|
def get_context(cls, records, header, data):
|
|
Configuration = Pool().get('carrier.configuration')
|
|
|
|
report_context = super(CMR, cls).get_context(records, header, data)
|
|
report_context['copies'] = Configuration(1).cmr_copies or 3
|
|
report_context['addresses'] = lambda order: cls.addresses(order)
|
|
report_context['sender_text'] = (lambda order, language, *args:
|
|
partial(cls.get_section_text, '1')(order, language, *args))
|
|
report_context['consignee_text'] = (lambda order, language, *args:
|
|
partial(cls.get_section_text, '2')(order, language, *args))
|
|
report_context['delivery_text'] = (lambda order, language, *args:
|
|
partial(cls.get_section_text, '3')(order, language, *args))
|
|
report_context['load_text'] = (lambda order, language, *args:
|
|
partial(cls.get_section_text, '4')(order, language, *args))
|
|
return report_context
|
|
|
|
@classmethod
|
|
def instructions(cls, order, language):
|
|
Order = Pool().get('carrier.load.order')
|
|
with Transaction().set_context(language=language):
|
|
value = Order(order.id).cmr_instructions
|
|
if value:
|
|
value = value.splitlines()
|
|
return value or []
|
|
|
|
@classmethod
|
|
def addresses(cls, order):
|
|
addresses = {
|
|
'sender': cls.sender_address(order, cls.sender(order)),
|
|
'consignee': cls.consignee_address(order),
|
|
'delivery': cls.delivery_address(order)
|
|
}
|
|
res = [addresses]
|
|
if order.cmr_template and order.cmr_template.copy_as_sender and \
|
|
addresses['sender'].party != order.company.party:
|
|
res.append({
|
|
'sender': order.company.party.address_get(type='invoice'),
|
|
'consignee': addresses['sender'],
|
|
'delivery': addresses['consignee']
|
|
})
|
|
return res
|
|
|
|
@classmethod
|
|
def get_section_text(cls, section, order, language, *args):
|
|
if not args or not args[0]:
|
|
return ''
|
|
|
|
return order.cmr_template and \
|
|
order.cmr_template.get_section_text(section, order,
|
|
language, *args) or ''
|
|
|
|
@classmethod
|
|
def execute(cls, ids, data):
|
|
with Transaction().set_context(_check_access=False):
|
|
# allow to print without sale group
|
|
return super().execute(ids, data)
|