changeset 48304d72685b in modules/sale_secondary_unit:default
details: 
https://hg.tryton.org/modules/sale_secondary_unit?cmd=changeset&node=48304d72685b
description:
        Add purchase_blanket_agreement and sale_blanket_agreement modules

        issue10962
        review391151002
diffstat:

 __init__.py                                              |    5 +
 sale.py                                                  |  110 ++++++++++++
 setup.py                                                 |    1 +
 tests/scenario_sale_blanket_agreement_secondary_unit.rst |  133 +++++++++++++++
 tests/test_module.py                                     |    2 +-
 tryton.cfg                                               |    1 +
 6 files changed, 251 insertions(+), 1 deletions(-)

diffs (300 lines):

diff -r b3787b2475d1 -r 48304d72685b __init__.py
--- a/__init__.py       Mon May 02 17:51:28 2022 +0200
+++ b/__init__.py       Mon Oct 10 18:35:01 2022 +0200
@@ -25,3 +25,8 @@
         sale.OpportunityLine,
         module='sale_secondary_unit', type_='model',
         depends=['sale_opportunity'])
+    Pool.register(
+        sale.BlanketAgreementLine,
+        sale.LineBlanketAgreement,
+        module='sale_secondary_unit', type_='model',
+        depends=['sale_blanket_agreement'])
diff -r b3787b2475d1 -r 48304d72685b sale.py
--- a/sale.py   Mon May 02 17:51:28 2022 +0200
+++ b/sale.py   Mon Oct 10 18:35:01 2022 +0200
@@ -189,3 +189,113 @@
             sale_line.secondary_quantity = self.quantity
             sale_line.secondary_unit = self.unit
             sale_line.on_change_secondary_quantity()
+
+
+class BlanketAgreementLine(metaclass=PoolMeta):
+    __name__ = 'sale.blanket_agreement.line'
+
+    product_secondary_uom_category = fields.Function(
+        fields.Many2One(
+            'product.uom.category', "Product Secondary UOM Category"),
+        'on_change_with_product_secondary_uom_category')
+
+    @classmethod
+    def _unit_categories(cls):
+        return super()._unit_categories() + ['product_secondary_uom_category']
+
+    def is_same_uom_category(self, sale_line):
+        return super().is_same_uom_category(sale_line) or (
+            sale_line.secondary_unit and (
+                self.unit.category == sale_line.secondary_unit.category))
+
+    def remainig_quantity_for_sale(self, line, round=True):
+        pool = Pool()
+        Uom = pool.get('product.uom')
+        remaining_quantity = super().remainig_quantity_for_sale(
+            line, round=round)
+        if (self.remaining_quantity is not None
+                and line.secondary_unit
+                and self.unit.category == line.secondary_unit.category):
+            remaining_quantity = Uom.compute_qty(
+                self.unit, self.remaining_quantity, line.unit,
+                factor=line.secondary_uom_rate,
+                rate=line.secondary_uom_factor,
+                round=round)
+        return remaining_quantity
+
+    @fields.depends('product')
+    def on_change_with_product_secondary_uom_category(self, name=None):
+        if self.product and self.product.sale_secondary_uom:
+            return self.product.sale_secondary_uom.category.id
+
+    def _set_sale_line_quantity(self, sale_line):
+        super()._set_sale_line_quantity(sale_line)
+        secondary_uom = self.product.sale_secondary_uom
+        if (secondary_uom
+                and self.unit.category == secondary_uom.category):
+            sale_line.unit = self.product.sale_uom
+            sale_line.secondary_quantity = self.remaining_quantity or 0
+            sale_line.secondary_unit = self.unit
+            sale_line.secondary_unit_price = self.unit_price
+            sale_line.on_change_secondary_quantity()
+
+
+class LineBlanketAgreement(metaclass=PoolMeta):
+    __name__ = 'sale.line'
+
+    @fields.depends(
+        'blanket_agreement_line', '_parent_blanket_agreement_line.unit',
+        '_parent_blanket_agreement_line.unit_price', 'unit', 'secondary_unit')
+    def compute_unit_price(self):
+        pool = Pool()
+        Uom = pool.get('product.uom')
+        unit_price = super().compute_unit_price()
+        line = self.blanket_agreement_line
+        if (line
+                and self.unit
+                and self.secondary_unit
+                and line.unit
+                and self.secondary_unit.category == line.unit.category):
+            secondary_unit_price = Uom.compute_price(
+                line.unit, line.unit_price, self.secondary_unit)
+            unit_price = Uom.compute_price(
+                self.secondary_unit, secondary_unit_price, self.unit,
+                factor=self.secondary_uom_rate, rate=self.secondary_uom_factor)
+            unit_price = round_price(unit_price)
+        return unit_price
+
+    @fields.depends(
+        'blanket_agreement_line',
+        '_parent_blanket_agreement_line.unit',
+        '_parent_blanket_agreement_line.remaining_quantity',
+        'sale', 'unit', 'secondary_quantity', 'secondary_unit',
+        'secondary_unit_price', methods=['on_change_secondary_quantity'])
+    def on_change_blanket_agreement_line(self):
+        pool = Pool()
+        Uom = pool.get('product.uom')
+        super().on_change_blanket_agreement_line()
+        if self.blanket_agreement_line:
+            line = self.blanket_agreement_line
+            if (self.secondary_unit and line.unit
+                    and self.secondary_unit.category == line.unit.category):
+                if line.remaining_quantity is not None:
+                    remaining_quantity = Uom.compute_qty(
+                        line.unit, line.remaining_quantity,
+                        self.secondary_unit)
+                    if (self.secondary_quantity is None
+                            or self.secondary_quantity > remaining_quantity):
+                        self.secondary_quantity = remaining_quantity
+                        self.on_change_secondary_quantity()
+
+    def quantity_for_blanket_agreement(self, line, round=True):
+        pool = Pool()
+        Uom = pool.get('product.uom')
+        quantity = super().quantity_for_blanket_agreement(line, round=round)
+        if (self.secondary_unit
+                and self.secondary_unit.category == line.unit.category):
+            quantity = Uom.compute_qty(
+                self.unit, (self.actual_quantity or self.quantity), line.unit,
+                factor=self.secondary_uom_factor,
+                rate=self.secondary_uom_rate,
+                round=round)
+        return quantity
diff -r b3787b2475d1 -r 48304d72685b setup.py
--- a/setup.py  Mon May 02 17:51:28 2022 +0200
+++ b/setup.py  Mon Oct 10 18:35:01 2022 +0200
@@ -66,6 +66,7 @@
 
 tests_require = [get_require_version('proteus'),
     get_require_version('trytond_account_invoice_secondary_unit'),
+    get_require_version('trytond_sale_blanket_agreement'),
     get_require_version('trytond_stock_secondary_unit'),
     get_require_version('trytond_sale_product_customer')]
 dependency_links = []
diff -r b3787b2475d1 -r 48304d72685b 
tests/scenario_sale_blanket_agreement_secondary_unit.rst
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_sale_blanket_agreement_secondary_unit.rst  Mon Oct 10 
18:35:01 2022 +0200
@@ -0,0 +1,133 @@
+==============================================
+Sale Blanket Agreement Secondary Unit Scenario
+==============================================
+
+Imports::
+
+    >>> import datetime
+    >>> from dateutil.relativedelta import relativedelta
+    >>> from decimal import Decimal
+
+    >>> from proteus import Model, Wizard
+    >>> from trytond.tests.tools import activate_modules
+    >>> from trytond.modules.company.tests.tools import (
+    ...     create_company, get_company)
+    >>> from trytond.modules.account.tests.tools import (
+    ...     create_chart, get_accounts)
+
+    >>> today = datetime.date.today()
+    >>> later = today + relativedelta(days=30)
+
+
+Activate modules::
+
+    >>> config = activate_modules([
+    ...         'sale_secondary_unit', 'sale_blanket_agreement'])
+
+    >>> Party = Model.get('party.party')
+    >>> ProductCategory = Model.get('product.category')
+    >>> ProductUom = Model.get('product.uom')
+    >>> ProductTemplate = Model.get('product.template')
+    >>> SaleBlanketAgreement = Model.get('sale.blanket_agreement')
+
+Create company::
+
+    >>> _ = create_company()
+    >>> company = get_company()
+
+Create chart of accounts::
+
+    >>> _ = create_chart(company)
+    >>> accounts = get_accounts(company)
+
+Create customer::
+
+    >>> customer = Party(name="Customer")
+    >>> customer.save()
+
+Create account category::
+
+    >>> account_category = ProductCategory(name="Account Category")
+    >>> account_category.accounting = True
+    >>> account_category.account_expense = accounts['expense']
+    >>> account_category.account_revenue = accounts['revenue']
+    >>> account_category.save()
+
+Create product::
+
+    >>> unit, = ProductUom.find([('name', '=', 'Unit')])
+    >>> gr, = ProductUom.find([('name', '=', 'Gram')])
+    >>> template = ProductTemplate()
+    >>> template.name = "Product"
+    >>> template.default_uom = unit
+    >>> template.type = 'goods'
+    >>> template.list_price = Decimal('10.000')
+    >>> template.salable = True
+    >>> template.account_category = account_category
+    >>> template.sale_secondary_uom = gr
+    >>> template.sale_secondary_uom_factor = 100
+    >>> template.save()
+    >>> product, = template.products
+    >>> product.cost_price = Decimal('8.000')
+    >>> product.save()
+
+Create sale blanket agreement::
+
+    >>> blanket_agreement = SaleBlanketAgreement()
+    >>> blanket_agreement.customer = customer
+    >>> blanket_agreement.from_date = today
+    >>> blanket_agreement.to_date = later
+    >>> blanket_agreement_line = blanket_agreement.lines.new()
+    >>> blanket_agreement_line.product = product
+    >>> blanket_agreement_line.quantity = 800.0
+    >>> blanket_agreement_line.unit = gr
+    >>> blanket_agreement_line.unit_price = Decimal('9.000')
+    >>> blanket_agreement.click('run')
+    >>> blanket_agreement.state
+    'running'
+
+Create sale from blanket agreement::
+
+    >>> create_sale = Wizard(
+    ...     'sale.blanket_agreement.create_sale', [blanket_agreement])
+    >>> create_sale.form.lines[0].unit == gr
+    True
+    >>> create_sale.execute('create_sale')
+
+    >>> sale, = create_sale.actions[0]
+    >>> line, = sale.lines
+    >>> line.product == product
+    True
+
+    >>> line.secondary_unit == gr
+    True
+    >>> line.secondary_quantity
+    800.0
+    >>> line.secondary_unit_price
+    Decimal('9.0000')
+
+    >>> line.unit == unit
+    True
+    >>> line.quantity
+    8.0
+    >>> line.unit_price
+    Decimal('900.0000')
+
+    >>> line.secondary_quantity = 300.0
+    >>> sale.save()
+
+    >>> blanket_agreement.reload()
+    >>> blanket_agreement_line, = blanket_agreement.lines
+    >>> blanket_agreement_line.remaining_quantity
+    800.0
+
+Confirm sale::
+
+    >>> sale.click('quote')
+    >>> sale.click('confirm')
+    >>> sale.state
+    'processing'
+
+    >>> blanket_agreement_line.reload()
+    >>> blanket_agreement_line.remaining_quantity
+    500.0
diff -r b3787b2475d1 -r 48304d72685b tests/test_module.py
--- a/tests/test_module.py      Mon May 02 17:51:28 2022 +0200
+++ b/tests/test_module.py      Mon Oct 10 18:35:01 2022 +0200
@@ -9,7 +9,7 @@
     module = 'sale_secondary_unit'
     extras = [
         'account_invoice_secondary_unit', 'stock_secondary_unit',
-        'sale_product_customer']
+        'sale_product_customer', 'sale_blanket_agreement']
 
 
 del ModuleTestCase
diff -r b3787b2475d1 -r 48304d72685b tryton.cfg
--- a/tryton.cfg        Mon May 02 17:51:28 2022 +0200
+++ b/tryton.cfg        Mon Oct 10 18:35:01 2022 +0200
@@ -8,6 +8,7 @@
     stock
 extras_depend:
     account_invoice_secondary_unit
+    sale_blanket_agreement
     sale_opportunity
     sale_product_customer
     stock_secondary_unit

Reply via email to