changeset 84769bd18480 in modules/sale_shipment_cost:default
details: 
https://hg.tryton.org/modules/sale_shipment_cost?cmd=changeset&node=84769bd18480
description:
        Add carrier_carriage module

        issue11623
        review443451003
diffstat:

 __init__.py                |    3 +
 message.xml                |    3 -
 sale.py                    |   37 ++++++++-------
 stock.py                   |  104 ++++++++++++++++++++++++++++----------------
 view/shipment_out_form.xml |    2 +-
 5 files changed, 91 insertions(+), 58 deletions(-)

diffs (307 lines):

diff -r b1733b905ce3 -r 84769bd18480 __init__.py
--- a/__init__.py       Mon Aug 08 22:15:28 2022 +0200
+++ b/__init__.py       Sat Sep 10 17:35:38 2022 +0200
@@ -4,6 +4,9 @@
 from trytond.pool import Pool
 
 from . import account, party, sale, stock
+from .stock import ShipmentCostSaleMixin
+
+__all__ = ['register', 'ShipmentCostSaleMixin']
 
 
 def register():
diff -r b1733b905ce3 -r 84769bd18480 message.xml
--- a/message.xml       Mon Aug 08 22:15:28 2022 +0200
+++ b/message.xml       Sat Sep 10 17:35:38 2022 +0200
@@ -6,9 +6,6 @@
         <record model="ir.message" id="msg_sale_invalid_carrier">
             <field name="text">To confirm sale "%(sale)s" you must change the 
carrier "%(carrier)s".</field>
         </record>
-        <record model="ir.message" id="msg_sale_shipment_cost_unique">
-            <field name="text">A sale can have only one shipment cost 
line.</field>
-        </record>
         <record model="ir.message" 
id="msg_shipment_cost_invoice_missing_account_revenue">
             <field name="text">To invoice shipment cost of "%(shipment)s", you 
must define an account revenue for product "%(product)s".</field>
         </record>
diff -r b1733b905ce3 -r 84769bd18480 sale.py
--- a/sale.py   Mon Aug 08 22:15:28 2022 +0200
+++ b/sale.py   Sat Sep 10 17:35:38 2022 +0200
@@ -4,7 +4,7 @@
 
 from trytond import backend
 from trytond.i18n import gettext
-from trytond.model import ModelView, Unique, Workflow, fields
+from trytond.model import ModelView, Workflow, fields
 from trytond.modules.product import price_digits, round_price
 from trytond.modules.sale.exceptions import SaleConfirmError
 from trytond.pool import Pool, PoolMeta
@@ -214,10 +214,10 @@
         with Transaction().set_context(_shipment_cost_invoiced=list()):
             super().process(sales)
 
-    def _get_carrier_context(self):
+    def _get_carrier_context(self, carrier):
         return {}
 
-    def compute_shipment_cost(self):
+    def compute_shipment_cost(self, carrier):
         pool = Pool()
         Date = pool.get('ir.date')
         Currency = pool.get('currency.currency')
@@ -227,9 +227,9 @@
             if line.type == 'line'
             and line.product
             and line.product.type in Line.get_move_product_types())
-        if self.carrier and stockable:
-            with Transaction().set_context(self._get_carrier_context()):
-                cost, currency_id = self.carrier.get_sale_price()
+        if stockable:
+            with Transaction().set_context(self._get_carrier_context(carrier)):
+                cost, currency_id = carrier.get_sale_price()
             if cost is not None:
                 with Transaction().set_context(company=self.company.id):
                     today = Date.today()
@@ -241,8 +241,8 @@
 
     def set_shipment_cost(self):
         cost = None
-        if self.shipment_cost_method:
-            cost = self.compute_shipment_cost()
+        if self.carrier and self.shipment_cost_method:
+            cost = self.compute_shipment_cost(self.carrier)
         removed = []
         unit_price = None
         lines = list(self.lines or [])
@@ -254,15 +254,15 @@
                 removed.append(line)
         if cost is not None:
             lines.append(self.get_shipment_cost_line(
-                    cost, unit_price=unit_price))
+                    self.carrier, cost, unit_price=unit_price))
         self.lines = lines
         return removed
 
-    def get_shipment_cost_line(self, cost, unit_price=None):
+    def get_shipment_cost_line(self, carrier, cost, unit_price=None):
         pool = Pool()
         SaleLine = pool.get('sale.line')
 
-        product = self.carrier.carrier_product
+        product = carrier.carrier_product
 
         sequence = None
         if self.lines:
@@ -319,15 +319,18 @@
     @classmethod
     def __setup__(cls):
         super().__setup__()
-        t = cls.__table__()
-        cls._sql_constraints += [
-            ('sale_shipment_cost_unique',
-                Unique(t, t.sale, t.shipment_cost),
-                'sale_shipment_cost.msg_sale_shipment_cost_unique'),
-            ]
         # shipment_cost is needed to compute the unit_price
         cls.unit_price.depends.add('shipment_cost')
 
+    @classmethod
+    def __register__(cls, module):
+        table_h = cls.__table_handler__(module)
+
+        super().__register__(module)
+
+        # Migration from 6.4: drop shipment cost unique
+        table_h.drop_constraint('sale_shipment_cost_unique')
+
     @fields.depends('shipment_cost', 'unit_price')
     def compute_unit_price(self):
         unit_price = super().compute_unit_price()
diff -r b1733b905ce3 -r 84769bd18480 stock.py
--- a/stock.py  Mon Aug 08 22:15:28 2022 +0200
+++ b/stock.py  Sat Sep 10 17:35:38 2022 +0200
@@ -10,14 +10,15 @@
 from .exceptions import InvoiceShipmentCostError
 
 
-class ShipmentOut(metaclass=PoolMeta):
-    __name__ = 'stock.shipment.out'
+class ShipmentCostSaleMixin:
+    __slots__ = ()
 
     cost_sale_currency_used = fields.Function(fields.Many2One(
             'currency.currency', "Cost Sale Currency",
             states={
                 'invisible': Eval('cost_method') != 'shipment',
-                'readonly': (Eval('state').in_(['done', 'cancelled'])
+                'readonly': (
+                    Eval('shipment_cost_sale_readonly', True)
                     | ~Eval('cost_edit', False)),
                 }),
         'on_change_with_cost_sale_currency_used', setter='set_cost')
@@ -26,13 +27,14 @@
         states={
             'invisible': Eval('cost_method') != 'shipment',
             'required': Bool(Eval('cost_sale')),
-            'readonly': Eval('state').in_(['done', 'cancelled']),
+            'readonly': Eval('shipment_cost_sale_readonly', True),
             })
     cost_sale_used = fields.Function(fields.Numeric(
             "Cost Sale", digits=price_digits,
             states={
                 'invisible': Eval('cost_method') != 'shipment',
-                'readonly': (Eval('state').in_(['done', 'cancelled'])
+                'readonly': (
+                    Eval('shipment_cost_sale_readonly', True)
                     | ~Eval('cost_edit', False)),
                 }),
         'on_change_with_cost_sale_used', setter='set_cost')
@@ -42,34 +44,17 @@
             'invisible': Eval('cost_method') != 'shipment',
             })
 
-    cost_invoice_line = fields.Many2One('account.invoice.line',
-            'Cost Invoice Line', readonly=True)
+    cost_invoice_line = fields.Many2One(
+        'account.invoice.line', "Cost Invoice Line", readonly=True)
     cost_method = fields.Selection(
-        'get_cost_methods', 'Cost Method', readonly=True)
-
-    @classmethod
-    def __register__(cls, module):
-        table_h = cls.__table_handler__(module)
-        cursor = Transaction().connection.cursor()
-        table = cls.__table__()
+        'get_cost_methods', "Cost Method", readonly=True)
 
-        # Migration from 5.8: rename cost into cost_sale
-        if (table_h.column_exist('cost')
-                and not table_h.column_exist('cost_sale')):
-            table_h.column_rename('cost', 'cost_sale')
-        if (table_h.column_exist('cost_currency')
-                and not table_h.column_exist('cost_sale_currency')):
-            table_h.column_rename('cost_currency', 'cost_sale_currency')
+    shipment_cost_sale_readonly = fields.Function(
+        fields.Boolean("Shipment Cost Sale Read Only"),
+        'on_change_with_shipment_cost_sale_readonly')
 
-        cost_method_exists = table_h.column_exist('cost_method')
-
-        super().__register__(module)
-
-        # Migration from 6.0: fill new cost_method field
-        if not cost_method_exists:
-            cursor.execute(*table.update(
-                    columns=[table.cost_method],
-                    values=['shipment']))
+    def on_change_with_shipment_cost_sale_readonly(self, name=None):
+        raise NotImplementedError
 
     @fields.depends('carrier', 'cost_method', methods=['_get_carrier_context'])
     def _compute_costs(self):
@@ -87,17 +72,19 @@
         return costs
 
     @fields.depends(
-        'state', 'cost_sale', 'cost_edit', methods=['_compute_costs'])
+        'shipment_cost_sale_readonly', 'cost_sale', 'cost_edit',
+        methods=['_compute_costs'])
     def on_change_with_cost_sale_used(self, name=None):
-        if not self.cost_edit and self.state not in {'cancelled', 'done'}:
+        if not self.cost_edit and not self.shipment_cost_sale_readonly:
             return self._compute_costs()['cost_sale']
         else:
             return self.cost_sale
 
     @fields.depends(
-        'state', 'cost_sale_currency', 'cost_edit', methods=['_compute_costs'])
+        'shipment_cost_sale_readonly', 'cost_sale_currency', 'cost_edit',
+        methods=['_compute_costs'])
     def on_change_with_cost_sale_currency_used(self, name=None):
-        if not self.cost_edit and self.state not in {'cancelled', 'done'}:
+        if not self.cost_edit and not self.shipment_cost_sale_readonly:
             return self._compute_costs()['cost_sale_currency']
         elif self.cost_sale_currency:
             return self.cost_sale_currency.id
@@ -135,7 +122,6 @@
         invoice_line.unit_price = round_price(cost)
         invoice_line.product = product
         invoice_line.on_change_product()
-        invoice_line.cost_shipments = [self]
 
         if not invoice_line.account:
             raise InvoiceShipmentCostError(
@@ -155,8 +141,46 @@
                     self.cost_sale_currency, self.cost_sale,
                     self.company.currency, round=False)
                 cost -= cost_sale
-        elif self.cost_method == 'order':
-            sales = {m.sale for m in self.outgoing_moves if m.sale}
+        return cost
+
+
+class ShipmentOut(ShipmentCostSaleMixin, metaclass=PoolMeta):
+    __name__ = 'stock.shipment.out'
+
+    @classmethod
+    def __register__(cls, module):
+        table_h = cls.__table_handler__(module)
+        cursor = Transaction().connection.cursor()
+        table = cls.__table__()
+
+        # Migration from 5.8: rename cost into cost_sale
+        if (table_h.column_exist('cost')
+                and not table_h.column_exist('cost_sale')):
+            table_h.column_rename('cost', 'cost_sale')
+        if (table_h.column_exist('cost_currency')
+                and not table_h.column_exist('cost_sale_currency')):
+            table_h.column_rename('cost_currency', 'cost_sale_currency')
+
+        cost_method_exists = table_h.column_exist('cost_method')
+
+        super().__register__(module)
+
+        # Migration from 6.0: fill new cost_method field
+        if not cost_method_exists:
+            cursor.execute(*table.update(
+                    columns=[table.cost_method],
+                    values=['shipment']))
+
+    @fields.depends('state')
+    def on_change_with_shipment_cost_sale_readonly(self, name=None):
+        return self.state in {'done', 'cancelled'}
+
+    def _get_shipment_cost(self):
+        cost = super()._get_shipment_cost()
+        if self.cost_method == 'order':
+            sales = {
+                m.sale for m in self.outgoing_moves
+                if m.sale and m.sale.shipment_cost_method == 'order'}
             for sale in sales:
                 shipment_cost = sum(
                     (s.cost_used or 0) for s in sale.shipments
@@ -165,6 +189,12 @@
                 cost -= max(cost_sale - shipment_cost, 0)
         return cost
 
+    def get_cost_invoice_line(self, invoice):
+        invoice_line = super().get_cost_invoice_line(invoice)
+        if invoice_line:
+            invoice_line.cost_shipments = [self]
+        return invoice_line
+
     @classmethod
     @ModelView.button
     @Workflow.transition('done')
diff -r b1733b905ce3 -r 84769bd18480 view/shipment_out_form.xml
--- a/view/shipment_out_form.xml        Mon Aug 08 22:15:28 2022 +0200
+++ b/view/shipment_out_form.xml        Sat Sep 10 17:35:38 2022 +0200
@@ -6,7 +6,7 @@
         <label name="cost_sale_used"/>
         <group id="cost_sale_used" col="-1" colspan="3">
             <field name="cost_sale_used" xexpand="0"/>
-            <field name="cost_sale_currency_used" xexpand="0" xalign="0"/>
+            <field name="cost_sale_currency_used"/>
         </group>
     </xpath>
 </data>

Reply via email to