changeset dd06c21bc0a6 in modules/sale:default
details: https://hg.tryton.org/modules/sale?cmd=changeset&node=dd06c21bc0a6
description:
        Define default invoice and shipment methods by party

        issue10161
        review316991002
diffstat:

 CHANGELOG                               |   1 +
 __init__.py                             |   2 +
 party.py                                |  73 ++++++++++++++++++++++++++++++++-
 party.xml                               |  24 ++++++++++
 sale.py                                 |  10 ++++
 tests/scenario_sale_default_methods.rst |  37 ++++++++++++++++
 tests/test_sale.py                      |   5 ++
 view/party_form.xml                     |   4 +
 8 files changed, 155 insertions(+), 1 deletions(-)

diffs (235 lines):

diff -r b804b5645619 -r dd06c21bc0a6 CHANGELOG
--- a/CHANGELOG Mon Oct 11 17:19:03 2021 +0200
+++ b/CHANGELOG Mon Oct 11 22:40:54 2021 +0200
@@ -1,3 +1,4 @@
+* Define default invoice and shipment methods by party
 * Split process method
 * Add general reporting
 * Add reporting per customer category
diff -r b804b5645619 -r dd06c21bc0a6 __init__.py
--- a/__init__.py       Mon Oct 11 17:19:03 2021 +0200
+++ b/__init__.py       Mon Oct 11 22:40:54 2021 +0200
@@ -21,6 +21,8 @@
         sale.SaleLineTax,
         sale.SaleLineIgnoredMove,
         sale.SaleLineRecreatedMove,
+        party.Party,
+        party.PartySaleMethod,
         product.Configuration,
         product.DefaultLeadTime,
         product.Template,
diff -r b804b5645619 -r dd06c21bc0a6 party.py
--- a/party.py  Mon Oct 11 17:19:03 2021 +0200
+++ b/party.py  Mon Oct 11 22:40:54 2021 +0200
@@ -1,9 +1,80 @@
 # This file is part of Tryton.  The COPYRIGHT file at the top level of
 # this repository contains the full copyright notices and license terms.
 from trytond.i18n import gettext
+from trytond.model import ModelSQL, fields
 from trytond.pool import PoolMeta, Pool
+from trytond.pyson import Eval
+from trytond.transaction import Transaction
+
+from trytond.modules.company.model import (
+    CompanyMultiValueMixin, CompanyValueMixin)
+from trytond.modules.party.exceptions import EraseError
+
+
+def get_sale_methods(field_name):
+    @classmethod
+    def func(cls):
+        pool = Pool()
+        Sale = pool.get('sale.sale')
+        return Sale.fields_get([field_name])[field_name]['selection'] + [
+            (None, '')]
+    return func
+
+
+class Party(CompanyMultiValueMixin, metaclass=PoolMeta):
+    __name__ = 'party.party'
+
+    sale_invoice_method = fields.MultiValue(fields.Selection(
+            'get_sale_invoice_method', "Invoice Method",
+            help="The default sale invoice method for the customer.\n"
+            "Leave empty to use the default value from the configuration."))
+    sale_shipment_method = fields.MultiValue(fields.Selection(
+            'get_sale_shipment_method', "Shipment Method",
+            help="The default sale shipment method for the customer.\n"
+            "Leave empty to use the default value from the configuration."))
+    sale_methods = fields.One2Many(
+        'party.party.sale_method', 'party', "Sale Methods")
 
-from trytond.modules.party.exceptions import EraseError
+    @classmethod
+    def multivalue_model(cls, field):
+        pool = Pool()
+        if field in {'sale_invoice_method', 'sale_shipment_method'}:
+            return pool.get('party.party.sale_method')
+        return super().multivalue_model(field)
+
+    get_sale_invoice_method = get_sale_methods('invoice_method')
+    get_sale_shipment_method = get_sale_methods('shipment_method')
+
+    @classmethod
+    def copy(cls, parties, default=None):
+        context = Transaction().context
+        default = default.copy() if default else {}
+        if context.get('_check_access'):
+            fields = [
+                'sale_methods', 'sale_invoice_method', 'sale_shipment_method']
+            default_values = cls.default_get(fields, with_rec_name=False)
+            for fname in fields:
+                default.setdefault(fname, default_values.get(fname))
+        return super().copy(parties, default=default)
+
+
+class PartySaleMethod(ModelSQL, CompanyValueMixin):
+    "Party Sale Method"
+    __name__ = 'party.party.sale_method'
+
+    party = fields.Many2One(
+        'party.party', "Party", ondelete='CASCADE', select=True,
+        context={
+            'company': Eval('company', -1),
+            },
+        depends=['company'])
+    sale_invoice_method = fields.Selection(
+        'get_sale_invoice_method', "Sale Invoice Method")
+    sale_shipment_method = fields.Selection(
+        'get_sale_shipment_method', "Sale Shipment Method")
+
+    get_sale_invoice_method = get_sale_methods('invoice_method')
+    get_sale_shipment_method = get_sale_methods('shipment_method')
 
 
 class Replace(metaclass=PoolMeta):
diff -r b804b5645619 -r dd06c21bc0a6 party.xml
--- a/party.xml Mon Oct 11 17:19:03 2021 +0200
+++ b/party.xml Mon Oct 11 22:40:54 2021 +0200
@@ -22,5 +22,29 @@
             <field name="action" ref="act_sale_form2"/>
             <field name="group" ref="group_sale"/>
         </record>
+
+        <record model="ir.model.field.access" 
id="access_party_sale_invoice_method">
+            <field name="field" search="[('model.model', '=', 'party.party'), 
('name', '=', 'sale_invoice_method')]"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="False"/>
+        </record>
+        <record model="ir.model.field.access" 
id="access_party_sale_invoice_method_group_sale">
+            <field name="field" search="[('model.model', '=', 'party.party'), 
('name', '=', 'sale_invoice_method')]"/>
+            <field name="group" ref="group_sale"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="True"/>
+        </record>
+
+        <record model="ir.model.field.access" 
id="access_party_sale_shipment_method">
+            <field name="field" search="[('model.model', '=', 'party.party'), 
('name', '=', 'sale_shipment_method')]"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="False"/>
+        </record>
+        <record model="ir.model.field.access" 
id="access_party_sale_shipment_method_group_sale">
+            <field name="field" search="[('model.model', '=', 'party.party'), 
('name', '=', 'sale_shipment_method')]"/>
+            <field name="group" ref="group_sale"/>
+            <field name="perm_read" eval="True"/>
+            <field name="perm_write" eval="True"/>
+        </record>
     </data>
 </tryton>
diff -r b804b5645619 -r dd06c21bc0a6 sale.py
--- a/sale.py   Mon Oct 11 17:19:03 2021 +0200
+++ b/sale.py   Mon Oct 11 22:40:54 2021 +0200
@@ -433,8 +433,16 @@
                 self.invoice_address = self.party.address_get(type='invoice')
             if not self.shipment_party:
                 self.shipment_address = self.party.address_get(type='delivery')
+                if self.party.sale_shipment_method:
+                    self.shipment_method = self.party.sale_shipment_method
+                else:
+                    self.shipment_method = self.default_shipment_method()
             if self.party.customer_payment_term:
                 self.payment_term = self.party.customer_payment_term
+            if self.party.sale_invoice_method:
+                self.invoice_method = self.party.sale_invoice_method
+            else:
+                self.invoice_method = self.default_invoice_method()
 
     @fields.depends('party', 'invoice_party')
     def on_change_invoice_party(self):
@@ -451,6 +459,8 @@
                 type='delivery')
         elif self.party:
             self.shipment_address = self.party.address_get(type='delivery')
+            if self.party.sale_shipment_method:
+                self.shipment_method = self.party.sale_shipment_method
 
     @fields.depends('party', 'company')
     def _get_tax_context(self):
diff -r b804b5645619 -r dd06c21bc0a6 tests/scenario_sale_default_methods.rst
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_sale_default_methods.rst   Mon Oct 11 22:40:54 2021 +0200
@@ -0,0 +1,37 @@
+=============================
+Sale Default Methods Scenario
+=============================
+
+Imports::
+
+    >>> from proteus import Model, Wizard, Report
+    >>> from trytond.tests.tools import activate_modules, set_user
+    >>> from trytond.modules.company.tests.tools import create_company, \
+    ...     get_company
+
+Activate modules::
+
+    >>> config = activate_modules('sale')
+
+Create company::
+
+    >>> _ = create_company()
+    >>> company = get_company()
+
+Create a party and set their default methods::
+
+    >>> Party = Model.get('party.party')
+    >>> customer = Party(name='Customer')
+    >>> customer.sale_shipment_method = 'invoice'
+    >>> customer.sale_invoice_method = 'shipment'
+    >>> customer.save()
+
+Create a sale to to check default methods::
+
+    >>> Sale = Model.get('sale.sale')
+    >>> sale = Sale()
+    >>> sale.party = customer
+    >>> sale.shipment_method
+    'invoice'
+    >>> sale.invoice_method
+    'shipment'
diff -r b804b5645619 -r dd06c21bc0a6 tests/test_sale.py
--- a/tests/test_sale.py        Mon Oct 11 17:19:03 2021 +0200
+++ b/tests/test_sale.py        Mon Oct 11 22:40:54 2021 +0200
@@ -88,4 +88,9 @@
             tearDown=doctest_teardown, encoding='utf-8',
             optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
             checker=doctest_checker))
+    suite.addTests(doctest.DocFileSuite(
+            'scenario_sale_default_methods.rst',
+            tearDown=doctest_teardown, encoding='utf-8',
+            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
+            checker=doctest_checker))
     return suite
diff -r b804b5645619 -r dd06c21bc0a6 view/party_form.xml
--- a/view/party_form.xml       Mon Oct 11 17:19:03 2021 +0200
+++ b/view/party_form.xml       Mon Oct 11 22:40:54 2021 +0200
@@ -7,6 +7,10 @@
     </xpath>
     <xpath expr="/form/notebook" position="inside">
         <page id="sale" string="Sale">
+            <label name="sale_invoice_method"/>
+            <field name="sale_invoice_method"/>
+            <label name="sale_shipment_method"/>
+            <field name="sale_shipment_method"/>
         </page>
     </xpath>
 </data>

Reply via email to