Migrate to 6.0

This commit is contained in:
José Miguel Pardo Salar 2021-10-11 19:02:56 +02:00
parent 0975bb5094
commit 93ee3fc231
15 changed files with 175 additions and 155 deletions

View File

@ -1,10 +1,7 @@
# The COPYRIGHT file at the top level of # The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms. # this repository contains the full copyright notices and license terms.
from trytond.model import fields
from trytond.pool import PoolMeta from trytond.pool import PoolMeta
__all__ = ['Carrier']
class Carrier(metaclass=PoolMeta): class Carrier(metaclass=PoolMeta):
__name__ = 'carrier' __name__ = 'carrier'

1
cmr.py
View File

@ -11,7 +11,6 @@ from .load import NoteMixin
from genshi.template import TextTemplate from genshi.template import TextTemplate
from sql import Literal from sql import Literal
__all__ = ['CMRTemplate', 'CMRTemplateLine', 'CMR']
file_id = 'cmr_template_image_id' file_id = 'cmr_template_image_id'
store_prefix = None store_prefix = None

View File

@ -6,10 +6,8 @@ from trytond.pyson import Eval, Id
from trytond.transaction import Transaction from trytond.transaction import Transaction
from trytond.modules.company.model import CompanyValueMixin from trytond.modules.company.model import CompanyValueMixin
from trytond.tools.multivalue import migrate_property from trytond.tools.multivalue import migrate_property
from trytond import backend
from sql import Literal from sql import Literal
__all__ = ['Configuration', 'ConfigurationSequence']
config_names = ['load_sequence', 'load_order_sequence'] config_names = ['load_sequence', 'load_order_sequence']

109
load.py
View File

@ -20,6 +20,8 @@ from trytond.modules.stock_location_dock.stock import DockMixin
from trytond.modules.product import price_digits from trytond.modules.product import price_digits
from trytond.wizard import StateReport, Wizard, StateView, \ from trytond.wizard import StateReport, Wizard, StateView, \
StateTransition, Button StateTransition, Button
from trytond.exceptions import UserError
from trytond.i18n import gettext
from decimal import Decimal from decimal import Decimal
try: try:
import phonenumbers import phonenumbers
@ -41,12 +43,6 @@ except ModuleNotFoundError:
return wrapper return wrapper
__all__ = ['Load', 'LoadOrder', 'LoadOrderLine',
'LoadOrderIncoterm', 'LoadSheet', 'RoadTransportNote',
'PrintLoadOrderShipment', 'Load2', 'Load3',
'LoadOrder3', 'CarrierLoadPurchase', 'PrintCarrierLoadPurchase']
# XXX fix: https://genshi.edgewall.org/ticket/582 # XXX fix: https://genshi.edgewall.org/ticket/582
from genshi.template.astutil import ASTCodeGenerator, ASTTransformer from genshi.template.astutil import ASTCodeGenerator, ASTTransformer
if not hasattr(ASTCodeGenerator, 'visit_NameConstant'): if not hasattr(ASTCodeGenerator, 'visit_NameConstant'):
@ -227,7 +223,7 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
t = cls.__table__() t = cls.__table__()
cls._sql_constraints = [ cls._sql_constraints = [
('code_uk1', Unique(t, t.code), ('code_uk1', Unique(t, t.code),
'Code must be unique.') 'carrier_load.msg_carrier_load_code_uk1')
] ]
cls._order = [ cls._order = [
('date', 'DESC'), ('date', 'DESC'),
@ -239,18 +235,6 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
('done', 'confirmed'), ('done', 'confirmed'),
('draft', 'cancelled'), ('draft', 'cancelled'),
('cancelled', 'draft'))) ('cancelled', 'draft')))
cls._error_messages.update({
'delete_cancel':
'Carrier load "%s" must be cancelled before deletion.',
'purchase_price':
'Unit price in Load "%s" must be defined.',
'purchase_confirm':
'Carrier load "%s" must have no purchase to be confirmed.',
'invalid_phonenumber': ('The phone number "%(phone)s" '
'is not valid.'),
'missing_carrier_info':
'Must define either Carrier or Carrier information on Load "%s".'
})
cls._buttons.update({ cls._buttons.update({
'cancel': { 'cancel': {
'invisible': Eval('state').in_(['cancelled', 'done']), 'invisible': Eval('state').in_(['cancelled', 'done']),
@ -344,7 +328,9 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
if (record.state not in ('cancelled', 'draft') and if (record.state not in ('cancelled', 'draft') and
not record.carrier and not record.carrier and
not record.carrier_info): not record.carrier_info):
cls.raise_user_error('missing_carrier_info', record.rec_name) raise UserError(gettext(
'carrier_load.msg_carrier_load_missing_carrier_info',
load=record.rec_name))
record.check_valid_phonenumber() record.check_valid_phonenumber()
@classmethod @classmethod
@ -418,7 +404,8 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
def default_purchase_state(cls): def default_purchase_state(cls):
return None return None
@fields.depends('carrier', 'purchase') @fields.depends('carrier', 'purchase', 'currency', '_parent_carrier.id',
'_parent_currency.digits', '_parent_purchase.id')
def on_change_carrier(self): def on_change_carrier(self):
pool = Pool() pool = Pool()
Currency = pool.get('currency.currency') Currency = pool.get('currency.currency')
@ -453,10 +440,9 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
except NumberParseException: except NumberParseException:
phonenumber = None phonenumber = None
if not (phonenumber and phonenumbers.is_valid_number(phonenumber)): if not (phonenumber and phonenumbers.is_valid_number(phonenumber)):
self.raise_user_error( raise UserError(gettext(
'invalid_phonenumber', { 'carrier_load.msg_carrier_load_invalid_phonenumber',
'phone': self.driver_phone phone=self.driver_phone))
})
@classmethod @classmethod
def format_phone(cls, value=None): def format_phone(cls, value=None):
@ -587,7 +573,9 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
cls.cancel(records) cls.cancel(records)
for record in records: for record in records:
if record.state != 'cancelled': if record.state != 'cancelled':
cls.raise_user_error('delete_cancel', record.rec_name) raise UserError(gettext(
'carrier_load.msg_carrier_load_delete_cancel',
load=record.rec_name))
super(Load, cls).delete(records) super(Load, cls).delete(records)
@classmethod @classmethod
@ -613,7 +601,9 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
done_records = [r for r in records if r.state == 'done'] done_records = [r for r in records if r.state == 'done']
for record in done_records: for record in done_records:
if record.purchase: if record.purchase:
cls.raise_user_error('purchase_confirm', record.rec_name) raise UserError(gettext(
'carrier_load.msg_carrier_load_purchase_confirm',
load=record.rec_name))
@classmethod @classmethod
@ModelView.button @ModelView.button
@ -647,7 +637,9 @@ class Load(Workflow, ModelView, ModelSQL, DockMixin, CMRInstructionsMixin):
PurchaseLine = pool.get('purchase.line') PurchaseLine = pool.get('purchase.line')
if not self.unit_price: if not self.unit_price:
self.raise_user_error('purchase_price', self.rec_name) raise UserError(gettext(
'carrier_load.msg_carrier_load_purchase_price',
load=self.rec_name))
_party = (getattr(self.carrier.party, 'supplier_to_invoice', None) _party = (getattr(self.carrier.party, 'supplier_to_invoice', None)
or self.carrier.party) or self.carrier.party)
@ -797,7 +789,7 @@ class LoadOrder(Workflow, ModelView, ModelSQL, IncotermDocumentMixin,
t = cls.__table__() t = cls.__table__()
cls._sql_constraints = [ cls._sql_constraints = [
('code_uk1', Unique(t, t.code), ('code_uk1', Unique(t, t.code),
'Code must be unique.') 'carrier_load.msg_carrier_load_order_code_uk1')
] ]
cls._order = [ cls._order = [
('start_date', 'DESC'), ('start_date', 'DESC'),
@ -811,15 +803,6 @@ class LoadOrder(Workflow, ModelView, ModelSQL, IncotermDocumentMixin,
('running', 'done'), ('running', 'done'),
('draft', 'cancelled'), ('draft', 'cancelled'),
('cancelled', 'draft'))) ('cancelled', 'draft')))
cls._error_messages.update({
'delete_cancel': 'Carrier load order "%s" must be ' +
'cancelled before deletion.',
'non_salable_product': 'Product "%s" is not salable.',
'no_sale_line_found':
'Cannot find a line on Sale "%s" with following data:\n%s',
'missing_customer_location':
'Missing Customer location on Party "%s".'
})
cls._buttons.update({ cls._buttons.update({
'cancel': { 'cancel': {
'invisible': Eval('state').in_(['cancelled', 'done']), 'invisible': Eval('state').in_(['cancelled', 'done']),
@ -994,7 +977,7 @@ class LoadOrder(Workflow, ModelView, ModelSQL, IncotermDocumentMixin,
'stock.shipment.internal', 'stock.shipment.internal',
'stock.shipment.in.return'] 'stock.shipment.in.return']
@fields.depends('load') @fields.depends('load', '_parent_load.date')
def on_change_with_date(self, name=None): def on_change_with_date(self, name=None):
if self.load: if self.load:
return self.load.date return self.load.date
@ -1005,7 +988,9 @@ class LoadOrder(Workflow, ModelView, ModelSQL, IncotermDocumentMixin,
cls.cancel(records) cls.cancel(records)
for record in records: for record in records:
if record.state != 'cancelled': if record.state != 'cancelled':
cls.raise_user_error('delete_cancel', record.rec_name) raise UserError(gettext(
'carrier_load.msg_carrier_load_order_delete_cancel',
order=record.rec_name))
super(LoadOrder, cls).delete(records) super(LoadOrder, cls).delete(records)
@classmethod @classmethod
@ -1046,8 +1031,9 @@ class LoadOrder(Workflow, ModelView, ModelSQL, IncotermDocumentMixin,
_end_date = datetime.datetime.now() _end_date = datetime.datetime.now()
for record in records: for record in records:
if record.type == 'out' and not record.party.customer_location: if record.type == 'out' and not record.party.customer_location:
cls.raise_user_error('missing_customer_location', raise UserError(gettext(
record.party.rec_name) 'carrier_load.msg_carrier_load_order_missing_customer_location',
party=record.party.rec_name))
if not record.end_date: if not record.end_date:
record.end_date = _end_date record.end_date = _end_date
record.save() record.save()
@ -1131,11 +1117,12 @@ class LoadOrder(Workflow, ModelView, ModelSQL, IncotermDocumentMixin,
sale_line = [l for l in self.sale.lines sale_line = [l for l in self.sale.lines
if get_line_values(l) == list(key_dict.values())] if get_line_values(l) == list(key_dict.values())]
if not sale_line: if not sale_line:
self.raise_user_error('no_sale_line_found', raise UserError(gettext(
(self.sale.rec_name, '\n'.join([ 'carrier_load.msg_carrier_load_order_no_sale_line_found',
sale=self.sale.rec_name,
data='\n'.join([
' - %s: %s' % (key, value) ' - %s: %s' % (key, value)
for key, value in key_dict.items()])) for key, value in key_dict.items()])))
)
sale_line, = sale_line sale_line, = sale_line
else: else:
sale_line = None sale_line = None
@ -1236,7 +1223,9 @@ class LoadOrder(Workflow, ModelView, ModelSQL, IncotermDocumentMixin,
line = Saleline(**values) line = Saleline(**values)
product = Product(line.product) product = Product(line.product)
if not product.salable: if not product.salable:
self.raise_user_error('non_salable_product', product.rec_name) raise UserError(gettext(
'carrier_load.msg_carrier_load_order_non_salable_product',
product=product.rec_name))
line.on_change_product() line.on_change_product()
if 'unit_price' in values: if 'unit_price' in values:
line.unit_price = values['unit_price'] line.unit_price = values['unit_price']
@ -1283,7 +1272,7 @@ class LoadOrderIncoterm(ModelView, ModelSQL, IncotermMixin):
def _get_relation_version(self): def _get_relation_version(self):
return self.order return self.order
@fields.depends('order') @fields.depends('order', '_parent_order.incoterm_version')
def on_change_with_version(self, name=None): def on_change_with_version(self, name=None):
return super(LoadOrderIncoterm, self).on_change_with_version(name) return super(LoadOrderIncoterm, self).on_change_with_version(name)
@ -1319,13 +1308,6 @@ class LoadOrderLine(ModelView, ModelSQL):
fields.Selection('get_order_states', 'Order state'), fields.Selection('get_order_states', 'Order state'),
'on_change_with_order_state') 'on_change_with_order_state')
@classmethod
def __setup__(cls):
super(LoadOrderLine, cls).__setup__()
cls._error_messages.update({
'quantity_exceeded': 'Cannot exceed quantity of "%s".',
})
@classmethod @classmethod
def _get_origin(cls): def _get_origin(cls):
return [''] return ['']
@ -1389,7 +1371,9 @@ class LoadOrderLine(ModelView, ModelSQL):
def _raise_check_origin_quantity(cls, origin, fieldname, value): def _raise_check_origin_quantity(cls, origin, fieldname, value):
if origin and hasattr(origin, fieldname) and getattr(origin, if origin and hasattr(origin, fieldname) and getattr(origin,
fieldname, 0) < value: fieldname, 0) < value:
cls.raise_user_error('quantity_exceeded', origin.rec_name) raise UserError(gettext(
'carrier_load.msg_carrier_load_order_line_quantity_exceeded',
origin=origin.rec_name))
@classmethod @classmethod
def _get_quantity_field(cls): def _get_quantity_field(cls):
@ -1623,8 +1607,7 @@ class RoadTransportNote(NoteMixin, CompanyReport):
def get_context(cls, records, header, data): def get_context(cls, records, header, data):
Configuration = Pool().get('carrier.configuration') Configuration = Pool().get('carrier.configuration')
report_context = super(RoadTransportNote, cls).get_context( report_context = super().get_context(records, header, data)
records, data)
report_context['law_header'] = lambda language: \ report_context['law_header'] = lambda language: \
cls.law_header(language) cls.law_header(language)
@ -1809,13 +1792,6 @@ class CarrierDefine(Wizard):
Button('Add', 'add', 'tryton-ok', default=True)]) Button('Add', 'add', 'tryton-ok', default=True)])
add = StateTransition() add = StateTransition()
@classmethod
def __setup__(cls):
super().__setup__()
cls._error_messages.update({
'many_warehouses': 'Warehouse must match.'
})
def transition_start(self): def transition_start(self):
Model = Pool().get(Transaction().context.get('active_model')) Model = Pool().get(Transaction().context.get('active_model'))
@ -1823,7 +1799,8 @@ class CarrierDefine(Wizard):
records = Model.browse(Transaction().context['active_ids']) records = Model.browse(Transaction().context['active_ids'])
whs = set(r.warehouse for r in records) whs = set(r.warehouse for r in records)
if len(whs) > 1: if len(whs) > 1:
self.raise_user_error('many_warehouses') raise UserError(gettext(
'carrier_load.msg_carrier_load_define_many_warehouses'))
return 'carrier' return 'carrier'
def default_carrier(self, fields): def default_carrier(self, fields):

View File

@ -90,12 +90,13 @@ this repository contains the full copyright notices and license terms. -->
</record> </record>
<record model="ir.rule.group" id="rule_group_carrier_load"> <record model="ir.rule.group" id="rule_group_carrier_load">
<field name="name">User in companies</field>
<field name="model" search="[('model', '=', 'carrier.load')]"/> <field name="model" search="[('model', '=', 'carrier.load')]"/>
<field name="global_p" eval="True"/> <field name="global_p" eval="True"/>
</record> </record>
<record model="ir.rule" id="rule_carrier_load"> <record model="ir.rule" id="rule_carrier_load">
<field name="domain" <field name="domain"
eval="[('company', '=', Eval('user', {}).get('company', None))]" eval="[('company', 'in', Eval('companies', []))]"
pyson="1"/> pyson="1"/>
<field name="rule_group" ref="rule_group_carrier_load"/> <field name="rule_group" ref="rule_group_carrier_load"/>
</record> </record>
@ -246,12 +247,13 @@ this repository contains the full copyright notices and license terms. -->
</record> </record>
<record model="ir.rule.group" id="rule_group_carrier_load_order"> <record model="ir.rule.group" id="rule_group_carrier_load_order">
<field name="name">User in companies</field>
<field name="model" search="[('model', '=', 'carrier.load.order')]"/> <field name="model" search="[('model', '=', 'carrier.load.order')]"/>
<field name="global_p" eval="True"/> <field name="global_p" eval="True"/>
</record> </record>
<record model="ir.rule" id="rule_carrier_load_order"> <record model="ir.rule" id="rule_carrier_load_order">
<field name="domain" <field name="domain"
eval="[('company', '=', Eval('user', {}).get('company', None))]" eval="[('company', 'in', Eval('companies', []))]"
pyson="1"/> pyson="1"/>
<field name="rule_group" ref="rule_group_carrier_load_order"/> <field name="rule_group" ref="rule_group_carrier_load_order"/>
</record> </record>

View File

@ -613,7 +613,7 @@
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/> <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
</text:sequence-decls> </text:sequence-decls>
<text:p text:style-name="P3"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;load in records&quot;&gt;</text:placeholder></text:p> <text:p text:style-name="P3"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;load in records&quot;&gt;</text:placeholder></text:p>
<text:p text:style-name="P4"><text:placeholder text:placeholder-type="text">&lt;set_lang(load.company.party.lang and load.company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;load.set_lang(load.company.party.lang and load.company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:p> <text:p text:style-name="P4"><text:placeholder text:placeholder-type="text">&lt;set_lang(load.company.party.lang and load.company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;load.set_lang(load.company.party.lang and load.company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p>
<text:p text:style-name="P5"/> <text:p text:style-name="P5"/>
<table:table table:name="Table1" table:style-name="Table1"> <table:table table:name="Table1" table:style-name="Table1">
<table:table-column table:style-name="Table1.A"/> <table:table-column table:style-name="Table1.A"/>

View File

@ -2,73 +2,69 @@
msgid "" msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n" msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "error:carrier.load.order.line:" msgctxt "model:ir.message,text:msg_carrier_load_order_line_quantity_exceeded"
msgid "Cannot exceed quantity of \"%s\"." msgid "Cannot exceed quantity of \"%(origin)s\"."
msgstr "No puede exceder la cantidad de carga de \"%s\"." msgstr "No puede exceder la cantidad de carga de \"%(origin)s\"."
msgctxt "error:carrier.load.order:" msgctxt "model:ir.message,text:msg_carrier_load_order_delete_cancel"
msgid "" msgid "Carrier load order \"%(order)s\" must be cancelled before deletion."
"Cannot find a line on Sale \"%s\" with following data:\n" msgstr "La orden de carga \"%(order)s\" debe cancelarse antes de ser eliminada."
"%s"
msgstr ""
"No ha sido posible encontrar una línea en la Venta \"%s\" con la información siguiente:\n"
"%s"
msgctxt "error:carrier.load.order:" msgctxt "model:ir.message,text:msg_carrier_load_order_code_uk1"
msgid "Carrier load order \"%s\" must be cancelled before deletion."
msgstr "La orden de carga \"%s\" debe cancelarse antes de ser eliminada."
msgctxt "error:carrier.load.order:"
msgid "Code must be unique." msgid "Code must be unique."
msgstr "Código debe ser único." msgstr "Código debe ser único."
msgctxt "error:carrier.load.order:" msgctxt "model:ir.message,text:msg_carrier_load_order_non_salable_product"
msgid "Product \"%s\" is not salable." msgid "Product \"%(product)s\" is not salable."
msgstr "El producto \"%s\" debe ser vendible." msgstr "El producto \"%(product)s\" debe ser vendible."
msgctxt "error:carrier.load:" msgctxt "model:ir.message,text:msg_carrier_load_delete_cancel"
msgid "Carrier load \"%s\" must be cancelled before deletion." msgid "Carrier load \"%(load)s\" must be cancelled before deletion."
msgstr "La carga \"%s\" debe cancelarse antes de ser eliminada." msgstr "La carga \"%(load)s\" debe cancelarse antes de ser eliminada."
msgctxt "error:carrier.load:" msgctxt "model:ir.message,text:msg_carrier_load_purchase_confirm"
msgid "Carrier load \"%s\" must have no purchase to be confirmed." msgid "Carrier load \"%(a)s\" must have no purchase to be confirmed."
msgstr "" msgstr ""
"La carga \"%s\" no debe tener compra para poder volver a estado confirmada." "La carga \"%(a)s\" no debe tener compra para poder volver a estado confirmada."
msgctxt "error:carrier.load:" msgctxt "model:ir.message,text:msg_carrier_load_code_uk1"
msgid "Code must be unique." msgid "Code must be unique."
msgstr "Código debe ser único." msgstr "Código debe ser único."
msgctxt "error:carrier.load:" msgctxt "model:ir.message,text:msg_carrier_load_missing_carrier_info"
msgid "Must define either Carrier or Carrier information on Load \"%s\"." msgid "Must define either Carrier or Carrier information on Load \"%(load)s\"."
msgstr "" msgstr ""
"Debe definir Transportista o Información de transportista en la Carga " "Debe definir Transportista o Información de transportista en la Carga "
"\"%s\"." "\"%(load)s\"."
msgctxt "error:carrier.load:" msgctxt "model:ir.message,text:msg_carrier_load_invalid_phonenumber"
msgid "The phone number \"%(phone)s\" is not valid." msgid "The phone number \"%(phone)s\" is not valid."
msgstr "El número de teléfono \"%(phone)s\" no es válido." msgstr "El número de teléfono \"%(phone)s\" no es válido."
msgctxt "error:carrier.load:" msgctxt "model:ir.message,text:msg_carrier_load_purchase_price"
msgid "Unit price in Load \"%s\" must be defined." msgid "Unit price in Load \"%(load)s\" must be defined."
msgstr "Debe definir precio en la Carga \"%s\"." msgstr "Debe definir precio en la Carga \"%(load)s\"."
msgctxt "error:carrier.load.order:" msgctxt "model:ir.message,text:msg_carrier_load_order_missing_customer_location"
msgid "Missing Customer location on Party \"%s\"." msgid "Missing Customer location on Party \"%(party)s\"."
msgstr "Falta la ubicación de cliente en el tercero \"%s\"." msgstr "Falta la ubicación de cliente en el tercero \"%(party)s\"."
msgctxt "error:sale.change.party:" msgctxt "model:ir.message,text:msg_sale_sale_has_load"
msgid "Shipment outgoing moves are in Done state." msgid "Cannot delete Sale \"%(sale)s\" due to it has load orders."
msgstr "Los movimientos de salida del albarán estan en estado Finalizado." msgstr "No puede eliminar la Venta \"%(sale)s\" porque tiene Ordenes de carga asociadas."
msgctxt "error:sale.sale:" msgctxt "model:ir.message,text:msg_carrier_load_define_many_warehouses"
msgid "Cannot delete Sale \"%s\" due to it has load orders."
msgstr "No puede eliminar la Venta \"%s\" porque tiene Ordenes de carga asociadas."
msgctxt "error:carrier.load.define:"
msgid "Warehouse must match." msgid "Warehouse must match."
msgstr "Almacén debe coincidir." msgstr "Almacén debe coincidir."
msgctxt "model:ir.message,text:msg_carrier_load_order_no_sale_line_found"
msgid ""
"Cannot find a line on Sale \"%(sale)s\" with following data:\n"
"%(data)s"
msgstr ""
"No ha sido posible encontrar una línea en la Venta \"%(sale)s\" con la información siguiente:\n"
"%(data)s"
msgctxt "field:sale.sale,loads:" msgctxt "field:sale.sale,loads:"
msgid "Load orders" msgid "Load orders"
msgstr "Ordenes de carga" msgstr "Ordenes de carga"
@ -848,6 +844,14 @@ msgctxt "model:ir.model.button,string:load_order_wait_button"
msgid "Wait" msgid "Wait"
msgstr "En espera" msgstr "En espera"
msgctxt "model:ir.rule.group,name:rule_group_carrier_load"
msgid "User in companies"
msgstr "Usuario en las empresas"
msgctxt "model:ir.rule.group,name:rule_group_carrier_load_order"
msgid "User in companies"
msgstr "Usuario en las empresas"
msgctxt "model:ir.sequence,name:sequence_load" msgctxt "model:ir.sequence,name:sequence_load"
msgid "Carrier Load" msgid "Carrier Load"
msgstr "Carga de transportista" msgstr "Carga de transportista"

59
message.xml Normal file
View File

@ -0,0 +1,59 @@
<?xml version="1.0"?>
<!-- The COPYRIGHT file at the top level of this repository contains the full
copyright notices and license terms. -->
<tryton>
<data grouped="1">
<!-- carrier.load -->
<record model="ir.message" id="msg_carrier_load_delete_cancel">
<field name="text">Carrier load "%(load)s" must be cancelled before deletion.</field>
</record>
<record model="ir.message" id="msg_carrier_load_purchase_confirm">
<field name="text">Carrier load "%(load)s" must have no purchase to be confirmed.</field>
</record>
<record model="ir.message" id="msg_carrier_load_code_uk1">
<field name="text">Code must be unique.</field>
</record>
<record model="ir.message" id="msg_carrier_load_missing_carrier_info">
<field name="text">Must define either Carrier or Carrier information on Load "%(load)s".</field>
</record>
<record model="ir.message" id="msg_carrier_load_invalid_phonenumber">
<field name="text">The phone number "%(phone)s" is not valid.</field>
</record>
<record model="ir.message" id="msg_carrier_load_purchase_price">
<field name="text">Unit price in Load "%(load)s" must be defined.</field>
</record>
<!-- carrier.load.define -->
<record model="ir.message" id="msg_carrier_load_define_many_warehouses">
<field name="text">Warehouse must match.</field>
</record>
<!-- carrier.load.order -->
<record model="ir.message" id="msg_carrier_load_order_no_sale_line_found">
<field name="text">Cannot find a line on Sale "%(sale)s" with following data:
%(data)s</field>
</record>
<record model="ir.message" id="msg_carrier_load_order_delete_cancel">
<field name="text">Carrier load order "%(order)s" must be cancelled before deletion.</field>
</record>
<record model="ir.message" id="msg_carrier_load_order_code_uk1">
<field name="text">Code must be unique.</field>
</record>
<record model="ir.message" id="msg_carrier_load_order_missing_customer_location">
<field name="text">Missing Customer location on Party "%(party)s".</field>
</record>
<record model="ir.message" id="msg_carrier_load_order_non_salable_product">
<field name="text">Product "%(product)s" is not salable.</field>
</record>
<!-- carrier.load.order.line -->
<record model="ir.message" id="msg_carrier_load_order_line_quantity_exceeded">
<field name="text">Cannot exceed quantity of "%(origin)s".</field>
</record>
<!-- sale.sale -->
<record model="ir.message" id="msg_sale_sale_has_load">
<field name="text">Cannot delete Sale "%(sale)s" due to it has load orders.</field>
</record>
</data>
</tryton>

View File

@ -3,8 +3,6 @@
from trytond.model import fields from trytond.model import fields
from trytond.pool import PoolMeta from trytond.pool import PoolMeta
__all__ = ['Purchase']
class Purchase(metaclass=PoolMeta): class Purchase(metaclass=PoolMeta):
__name__ = 'purchase.purchase' __name__ = 'purchase.purchase'

View File

@ -1302,7 +1302,7 @@
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/> <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
</text:sequence-decls> </text:sequence-decls>
<text:p text:style-name="P76"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;order in records&quot;&gt;</text:placeholder><text:span text:style-name="T21"><text:placeholder text:placeholder-type="text">&lt;set_lang(company.party.lang and company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:span><text:span text:style-name="T21"><text:placeholder text:placeholder-type="text">&lt;order.set_lang(company.party.lang and company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:span></text:p> <text:p text:style-name="P76"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;order in records&quot;&gt;</text:placeholder><text:span text:style-name="T21"><text:placeholder text:placeholder-type="text">&lt;set_lang(company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:span><text:span text:style-name="T21"><text:placeholder text:placeholder-type="text">&lt;order.set_lang(company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:span></text:p>
<text:p text:style-name="P77"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;copy in range(1,copies + 1)&quot;&gt;</text:placeholder></text:p> <text:p text:style-name="P77"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;copy in range(1,copies + 1)&quot;&gt;</text:placeholder></text:p>
<text:p text:style-name="P16">ROAD TRANSPORT DOCUMENT</text:p> <text:p text:style-name="P16">ROAD TRANSPORT DOCUMENT</text:p>
<table:table table:name="Table1" table:style-name="Table1"> <table:table table:name="Table1" table:style-name="Table1">
@ -1354,7 +1354,7 @@
<table:covered-table-cell/> <table:covered-table-cell/>
<table:covered-table-cell/> <table:covered-table-cell/>
<table:table-cell table:style-name="Table1.N1" table:number-rows-spanned="2" table:number-columns-spanned="12" office:value-type="string"> <table:table-cell table:style-name="Table1.N1" table:number-rows-spanned="2" table:number-columns-spanned="12" office:value-type="string">
<text:p text:style-name="P19"><text:placeholder text:placeholder-type="text">&lt;law_header(company.party.lang and company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:p> <text:p text:style-name="P19"><text:placeholder text:placeholder-type="text">&lt;law_header(company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
<table:covered-table-cell/> <table:covered-table-cell/>
<table:covered-table-cell/> <table:covered-table-cell/>
@ -1748,22 +1748,22 @@
<text:p text:style-name="P42"/> <text:p text:style-name="P42"/>
</table:table-cell> </table:table-cell>
<table:table-cell table:style-name="Table2.A1" office:value-type="string"> <table:table-cell table:style-name="Table2.A1" office:value-type="string">
<text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;product_brand(product, origins, company.party.lang and company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:p> <text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;product_brand(product, origins, company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
<table:table-cell table:style-name="Table2.A1" office:value-type="string"> <table:table-cell table:style-name="Table2.A1" office:value-type="string">
<text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;format_number(product_packages(product, origins, company.party.lang and company.party.lang.code or &apos;en_US&apos;), company.party.lang, digits=0)&gt;</text:placeholder></text:p> <text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;format_number(product_packages(product, origins, company.party.lang and company.party.lang.code or &apos;en&apos;), company.party.lang, digits=0)&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
<table:table-cell table:style-name="Table2.A1" office:value-type="string"> <table:table-cell table:style-name="Table2.A1" office:value-type="string">
<text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;product_packing(product, origins, company.party.lang and company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:p> <text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;product_packing(product, origins, company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
<table:table-cell table:style-name="Table2.A1" office:value-type="string"> <table:table-cell table:style-name="Table2.A1" office:value-type="string">
<text:p text:style-name="P7"><text:placeholder text:placeholder-type="text">&lt;product_name(order, product, origins, company.party.lang and company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:p> <text:p text:style-name="P7"><text:placeholder text:placeholder-type="text">&lt;product_name(order, product, origins, company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
<table:table-cell table:style-name="Table2.A1" office:value-type="string"> <table:table-cell table:style-name="Table2.A1" office:value-type="string">
<text:p text:style-name="P42"/> <text:p text:style-name="P42"/>
</table:table-cell> </table:table-cell>
<table:table-cell table:style-name="Table2.A1" office:value-type="string"> <table:table-cell table:style-name="Table2.A1" office:value-type="string">
<text:p text:style-name="P9"><text:placeholder text:placeholder-type="text">&lt;if test=&quot;product_weight(product, origins, &apos;en&apos;)&quot;&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;format_number(product_weight(product, origins, company.party.lang and company.party.lang.code or &apos;en_US&apos;), company.party.lang, digits=2)&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;/if&gt;</text:placeholder></text:p> <text:p text:style-name="P9"><text:placeholder text:placeholder-type="text">&lt;if test=&quot;product_weight(product, origins, &apos;en&apos;)&quot;&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;format_number(product_weight(product, origins, company.party.lang and company.party.lang.code or &apos;en&apos;), company.party.lang, digits=2)&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;/if&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
<table:table-cell table:style-name="Table2.A1" office:value-type="string"> <table:table-cell table:style-name="Table2.A1" office:value-type="string">
<text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;product_volume(product, origins, company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p> <text:p text:style-name="P8"><text:placeholder text:placeholder-type="text">&lt;product_volume(product, origins, company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p>
@ -1983,7 +1983,7 @@
<table:covered-table-cell/> <table:covered-table-cell/>
<table:covered-table-cell/> <table:covered-table-cell/>
<table:table-cell table:style-name="Table1.N21" table:number-rows-spanned="4" table:number-columns-spanned="8" office:value-type="string"> <table:table-cell table:style-name="Table1.N21" table:number-rows-spanned="4" table:number-columns-spanned="8" office:value-type="string">
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;line in instructions(order, company.party.lang and company.party.lang.code or &apos;en_US&apos;)&quot;&gt;</text:placeholder></text:p> <text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;line in instructions(order, company.party.lang and company.party.lang.code or &apos;en&apos;)&quot;&gt;</text:placeholder></text:p>
<text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;line&gt;</text:placeholder></text:p> <text:p text:style-name="P13"><text:placeholder text:placeholder-type="text">&lt;line&gt;</text:placeholder></text:p>
<text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;/for&gt;</text:placeholder></text:p> <text:p text:style-name="P14"><text:placeholder text:placeholder-type="text">&lt;/for&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
@ -2257,7 +2257,7 @@
<table:covered-table-cell/> <table:covered-table-cell/>
<table:covered-table-cell/> <table:covered-table-cell/>
<table:table-cell table:style-name="Table1.N26" table:number-columns-spanned="12" office:value-type="string"> <table:table-cell table:style-name="Table1.N26" table:number-columns-spanned="12" office:value-type="string">
<text:p text:style-name="P20"><text:placeholder text:placeholder-type="text">&lt;law_footer(company.party.lang and company.party.lang.code or &apos;en_US&apos;)&gt;</text:placeholder></text:p> <text:p text:style-name="P20"><text:placeholder text:placeholder-type="text">&lt;law_footer(company.party.lang and company.party.lang.code or &apos;en&apos;)&gt;</text:placeholder></text:p>
</table:table-cell> </table:table-cell>
<table:covered-table-cell/> <table:covered-table-cell/>
<table:covered-table-cell/> <table:covered-table-cell/>

13
sale.py
View File

@ -5,6 +5,8 @@ from trytond.model import fields
from trytond.pool import PoolMeta, Pool from trytond.pool import PoolMeta, Pool
from trytond.pyson import Eval from trytond.pyson import Eval
from trytond.transaction import Transaction from trytond.transaction import Transaction
from trytond.exceptions import UserError
from trytond.i18n import gettext
class Sale(metaclass=PoolMeta): class Sale(metaclass=PoolMeta):
@ -12,13 +14,6 @@ class Sale(metaclass=PoolMeta):
loads = fields.One2Many('carrier.load.order', 'sale', 'Load orders') loads = fields.One2Many('carrier.load.order', 'sale', 'Load orders')
@classmethod
def __setup__(cls):
super(Sale, cls).__setup__()
cls._error_messages.update({
'has_load': 'Cannot delete Sale "%s" due to it has load orders.'
})
@classmethod @classmethod
def _get_origin(cls): def _get_origin(cls):
res = super(Sale, cls)._get_origin() res = super(Sale, cls)._get_origin()
@ -29,7 +24,9 @@ class Sale(metaclass=PoolMeta):
def delete(cls, records): def delete(cls, records):
for record in records: for record in records:
if record.loads and not record.origin: if record.loads and not record.origin:
cls.raise_user_error('has_load', record.rec_name) raise UserError(gettext(
'carrier_load.msg_sale_sale_has_load',
sale=record.rec_name))
super(Sale, cls).delete(records) super(Sale, cls).delete(records)
@classmethod @classmethod

View File

@ -5,9 +5,6 @@ from trytond.pool import PoolMeta, Pool
from trytond.wizard import Wizard, StateTransition, StateView, Button from trytond.wizard import Wizard, StateTransition, StateView, Button
from trytond.transaction import Transaction from trytond.transaction import Transaction
__all__ = ['Move', 'ShipmentOut', 'ShipmentInternal',
'LoadShipment', 'ShipmentOutReturn', 'ShipmentInReturn']
class Move(metaclass=PoolMeta): class Move(metaclass=PoolMeta):
__name__ = 'stock.move' __name__ = 'stock.move'

View File

@ -38,13 +38,6 @@ Create chart of accounts::
>>> accounts = get_accounts(company) >>> accounts = get_accounts(company)
>>> revenue = accounts['revenue'] >>> revenue = accounts['revenue']
>>> expense = accounts['expense'] >>> expense = accounts['expense']
>>> cash = accounts['cash']
>>> Journal = Model.get('account.journal')
>>> cash_journal, = Journal.find([('type', '=', 'cash')])
>>> cash_journal.credit_account = cash
>>> cash_journal.debit_account = cash
>>> cash_journal.save()
Create tax:: Create tax::
@ -129,7 +122,7 @@ Create carrier load::
>>> load.save() >>> load.save()
Traceback (most recent call last): Traceback (most recent call last):
... ...
trytond.exceptions.UserError: The field "Driver identifier" on "Carrier load" is required. - trytond.model.modelstorage.RequiredValidationError: A value is required for field "Driver identifier" in "Carrier load". -
>>> load.driver_identifier = 'ID-Driver' >>> load.driver_identifier = 'ID-Driver'
>>> load.driver_phone = '+34968057451' >>> load.driver_phone = '+34968057451'
>>> load.save() >>> load.save()
@ -224,19 +217,19 @@ Check reports::
>>> ext >>> ext
'odt' 'odt'
>>> name >>> name
'Load sheet' 'Load sheet-1'
>>> cmr = Report('carrier.load.order.cmr') >>> cmr = Report('carrier.load.order.cmr')
>>> ext, _, _, name = cmr.execute([load.orders[0]], {}) >>> ext, _, _, name = cmr.execute([load.orders[0]], {})
>>> ext >>> ext
'odt' 'odt'
>>> name >>> name
'CMR' 'CMR-1'
>>> road_note = Report('carrier.load.order.road_note') >>> road_note = Report('carrier.load.order.road_note')
>>> ext, _, _, name = road_note.execute([load.orders[0]], {}) >>> ext, _, _, name = road_note.execute([load.orders[0]], {})
>>> ext >>> ext
'odt' 'odt'
>>> name >>> name
'Road transport note' 'Road transport note-1'
Check wizard purchase carrier load:: Check wizard purchase carrier load::

View File

@ -88,8 +88,6 @@ Create carrier::
>>> carrier.party = party_carrier >>> carrier.party = party_carrier
>>> carrier.carrier_product = carrier_product >>> carrier.carrier_product = carrier_product
>>> carrier.save() >>> carrier.save()
>>> carrier_product.account_expense = expense
>>> carrier_product.save()
>>> carrier2 = Carrier() >>> carrier2 = Carrier()
>>> carrier2.party = party_carrier2 >>> carrier2.party = party_carrier2
>>> carrier2.carrier_product = carrier_product >>> carrier2.carrier_product = carrier_product

View File

@ -26,3 +26,4 @@ xml:
sale.xml sale.xml
party.xml party.xml
cmr.xml cmr.xml
message.xml