mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[FIX] moved field potential_qty to stock_available module
This commit is contained in:
@@ -16,7 +16,7 @@ class ProductProduct(models.Model):
|
||||
|
||||
@api.multi
|
||||
@api.depends('virtual_available')
|
||||
def _immediately_usable_qty(self):
|
||||
def _compute_immediately_usable_qty(self):
|
||||
"""No-op implementation of the stock available to promise.
|
||||
|
||||
By default, available to promise = forecasted quantity.
|
||||
@@ -29,11 +29,26 @@ class ProductProduct(models.Model):
|
||||
for prod in self:
|
||||
prod.immediately_usable_qty = prod.virtual_available
|
||||
|
||||
@api.multi
|
||||
@api.depends()
|
||||
def _compute_potential_qty(self):
|
||||
"""Set potential qty to 0.0 to define the field defintion used by
|
||||
other modules to inherit it
|
||||
"""
|
||||
for product in self:
|
||||
product.potential_qty = 0.0
|
||||
|
||||
immediately_usable_qty = fields.Float(
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
compute='_immediately_usable_qty',
|
||||
compute='_compute_immediately_usable_qty',
|
||||
string='Available to promise',
|
||||
help="Stock for this Product that can be safely proposed "
|
||||
"for sale to Customers.\n"
|
||||
"The definition of this value can be configured to suit "
|
||||
"your needs")
|
||||
potential_qty = fields.Float(
|
||||
compute='_compute_potential_qty',
|
||||
digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
string='Potential',
|
||||
help="Quantity of this Product that could be produced using "
|
||||
"the materials already at hand.")
|
||||
|
||||
@@ -11,7 +11,7 @@ class ProductTemplate(models.Model):
|
||||
|
||||
@api.multi
|
||||
@api.depends('product_variant_ids.immediately_usable_qty')
|
||||
def _immediately_usable_qty(self):
|
||||
def _compute_immediately_usable_qty(self):
|
||||
"""No-op implementation of the stock available to promise.
|
||||
|
||||
By default, available to promise = forecasted quantity.
|
||||
@@ -24,11 +24,35 @@ class ProductTemplate(models.Model):
|
||||
for tmpl in self:
|
||||
tmpl.immediately_usable_qty = tmpl.virtual_available
|
||||
|
||||
@api.multi
|
||||
@api.depends('product_variant_ids.potential_qty')
|
||||
def _compute_potential_qty(self):
|
||||
"""Compute the potential as the max of all the variants's potential.
|
||||
|
||||
We can't add the potential of variants: if they share components we
|
||||
may not be able to make all the variants.
|
||||
So we set the arbitrary rule that we can promise up to the biggest
|
||||
variant's potential.
|
||||
"""
|
||||
for tmpl in self:
|
||||
if not tmpl.product_variant_ids:
|
||||
continue
|
||||
tmpl.potential_qty = max(
|
||||
[v.potential_qty for v in tmpl.product_variant_ids])
|
||||
|
||||
immediately_usable_qty = fields.Float(
|
||||
digits=dp.get_precision('Product Unit of Measure'),
|
||||
compute='_immediately_usable_qty',
|
||||
compute='_compute_immediately_usable_qty',
|
||||
string='Available to promise',
|
||||
help="Stock for this Product that can be safely proposed "
|
||||
"for sale to Customers.\n"
|
||||
"The definition of this value can be configured to suit "
|
||||
"your needs")
|
||||
potential_qty = fields.Float(
|
||||
compute='_compute_potential_qty',
|
||||
digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
string='Potential',
|
||||
help="Quantity of this Product that could be produced using "
|
||||
"the materials already at hand. "
|
||||
"If the product has several variants, this will be the biggest "
|
||||
"quantity that can be made for a any single variant.")
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
<!-- © 2014 Numérigraphe, Sodexis
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
<odoo>
|
||||
<record model="ir.ui.view" id="product_normal_form_view">
|
||||
<field name="name">Quantity available to promise (variant tree)</field>
|
||||
<field name="model">product.product</field>
|
||||
@@ -12,7 +11,7 @@
|
||||
<xpath expr="//button[@name='%(stock.action_stock_level_forecast_report_product)d']"
|
||||
position="after">
|
||||
<button type="action" name="%(stock.product_open_quants)d"
|
||||
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||
attrs="{'invisible':[('type', 'not in', ['product','consu'])]}"
|
||||
class="oe_stat_button" icon="fa-building-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<field name="immediately_usable_qty"
|
||||
@@ -20,8 +19,16 @@
|
||||
<span class="o_stat_text">Available</span>
|
||||
</div>
|
||||
</button>
|
||||
<button type="action" name="%(stock.product_open_quants)d"
|
||||
attrs="{'invisible':[('type', 'not in', ['product','consu'])]}"
|
||||
class="oe_stat_button" icon="fa-building-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<field name="potential_qty"
|
||||
widget="statinfo" nolabel="1"/>
|
||||
<span class="o_stat_text">Potential</span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
<!-- © 2014 Numérigraphe, Sodexis
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
<odoo>
|
||||
<record model="ir.ui.view" id="view_stock_available_form">
|
||||
<field name="name">Quantity available to promise (form)</field>
|
||||
<field name="model">product.template</field>
|
||||
@@ -12,7 +11,7 @@
|
||||
<xpath expr="//button[@name='%(stock.action_stock_level_forecast_report_template)d']"
|
||||
position="after">
|
||||
<button type="object" name="action_open_quants"
|
||||
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||
attrs="{'invisible':[('type', 'not in', ['product','consu'])]}"
|
||||
class="oe_stat_button" icon="fa-building-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<field name="immediately_usable_qty"
|
||||
@@ -20,6 +19,15 @@
|
||||
<span class="o_stat_text">Available</span>
|
||||
</div>
|
||||
</button>
|
||||
<button type="action" name="%(stock.product_open_quants)d"
|
||||
attrs="{'invisible':[('type', 'not in', ['product','consu'])]}"
|
||||
class="oe_stat_button" icon="fa-building-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<field name="potential_qty"
|
||||
widget="statinfo" nolabel="1"/>
|
||||
<span class="o_stat_text">Potential</span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
@@ -46,5 +54,4 @@
|
||||
</ul>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
<!-- © 2014 Numérigraphe, Sodexis
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
<odoo>
|
||||
<record id="view_stock_configuration" model="ir.ui.view">
|
||||
<field name="name">Stock settings: quantity available to promise</field>
|
||||
<field name="model">stock.config.settings</field>
|
||||
@@ -35,5 +34,4 @@
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -10,10 +10,10 @@ class ProductProduct(models.Model):
|
||||
|
||||
@api.multi
|
||||
@api.depends('virtual_available', 'incoming_qty')
|
||||
def _immediately_usable_qty(self):
|
||||
def _compute_immediately_usable_qty(self):
|
||||
"""Ignore the incoming goods in the quantity available to promise
|
||||
|
||||
This is the same implementation as for templates."""
|
||||
super(ProductProduct, self)._immediately_usable_qty()
|
||||
super(ProductProduct, self)._compute_immediately_usable_qty()
|
||||
for prod in self:
|
||||
prod.immediately_usable_qty -= prod.incoming_qty
|
||||
|
||||
@@ -26,10 +26,10 @@ class ProductTemplate(models.Model):
|
||||
|
||||
@api.multi
|
||||
@api.depends('virtual_available', 'incoming_qty')
|
||||
def _immediately_usable_qty(self):
|
||||
def _compute_immediately_usable_qty(self):
|
||||
"""Ignore the incoming goods in the quantity available to promise
|
||||
|
||||
This is the same implementation as for variants."""
|
||||
super(ProductTemplate, self)._immediately_usable_qty()
|
||||
super(ProductTemplate, self)._compute_immediately_usable_qty()
|
||||
for tmpl in self:
|
||||
tmpl.immediately_usable_qty -= tmpl.incoming_qty
|
||||
|
||||
@@ -5,15 +5,13 @@
|
||||
'name': 'Consider the production potential is available to promise',
|
||||
'version': '9.0.1.0.0',
|
||||
"author": u"Numérigraphe,"
|
||||
u"Sodexis,"
|
||||
u"Odoo Community Association (OCA)",
|
||||
'category': 'Hidden',
|
||||
'depends': [
|
||||
'stock_available',
|
||||
'mrp'
|
||||
],
|
||||
'data': [
|
||||
'views/product_template_view.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo/mrp_bom.yml',
|
||||
],
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
from collections import Counter
|
||||
|
||||
from openerp import models, fields, api
|
||||
from openerp.addons import decimal_precision as dp
|
||||
|
||||
from openerp.exceptions import AccessError
|
||||
|
||||
@@ -13,36 +12,32 @@ from openerp.exceptions import AccessError
|
||||
class ProductProduct(models.Model):
|
||||
_inherit = 'product.product'
|
||||
|
||||
potential_qty = fields.Float(
|
||||
compute='_get_potential_qty',
|
||||
type='float',
|
||||
digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
string='Potential',
|
||||
help="Quantity of this Product that could be produced using "
|
||||
"the materials already at hand.")
|
||||
|
||||
# Needed for fields dependencies
|
||||
# When self.potential_qty is compute, we want to force the ORM
|
||||
# to compute all the components potential_qty too.
|
||||
component_ids = fields.Many2many(
|
||||
comodel_name='product.product',
|
||||
compute='_get_component_ids',
|
||||
compute='_compute_component_ids',
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.depends('potential_qty')
|
||||
def _immediately_usable_qty(self):
|
||||
def _compute_immediately_usable_qty(self):
|
||||
"""Add the potential quantity to the quantity available to promise.
|
||||
|
||||
This is the same implementation as for templates."""
|
||||
super(ProductProduct, self)._immediately_usable_qty()
|
||||
super(ProductProduct, self)._compute_immediately_usable_qty()
|
||||
for product in self:
|
||||
product.immediately_usable_qty += product.potential_qty
|
||||
|
||||
@api.multi
|
||||
@api.depends('component_ids.potential_qty')
|
||||
def _get_potential_qty(self):
|
||||
def _compute_potential_qty(self):
|
||||
"""Compute the potential qty based on the available components."""
|
||||
|
||||
# call super method available in stock_available
|
||||
super(ProductProduct, self)._compute_potential_qty()
|
||||
|
||||
bom_obj = self.env['mrp.bom']
|
||||
uom_obj = self.env['product.uom']
|
||||
|
||||
@@ -121,7 +116,7 @@ class ProductProduct(models.Model):
|
||||
|
||||
return needs
|
||||
|
||||
def _get_component_ids(self):
|
||||
def _compute_component_ids(self):
|
||||
""" Compute component_ids by getting all the components for
|
||||
this product.
|
||||
"""
|
||||
|
||||
@@ -2,45 +2,18 @@
|
||||
# © 2014 Numérigraphe SARL
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from openerp import models, fields, api
|
||||
from openerp.addons import decimal_precision as dp
|
||||
from openerp import models, api
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
potential_qty = fields.Float(
|
||||
compute='_get_potential_qty',
|
||||
type='float',
|
||||
digits_compute=dp.get_precision('Product Unit of Measure'),
|
||||
string='Potential',
|
||||
help="Quantity of this Product that could be produced using "
|
||||
"the materials already at hand. "
|
||||
"If the product has several variants, this will be the biggest "
|
||||
"quantity that can be made for a any single variant.")
|
||||
|
||||
@api.multi
|
||||
@api.depends('potential_qty')
|
||||
def _immediately_usable_qty(self):
|
||||
def _compute_immediately_usable_qty(self):
|
||||
"""Add the potential quantity to the quantity available to promise.
|
||||
|
||||
This is the same implementation as for variants."""
|
||||
super(ProductTemplate, self)._immediately_usable_qty()
|
||||
super(ProductTemplate, self)._compute_immediately_usable_qty()
|
||||
for tmpl in self:
|
||||
tmpl.immediately_usable_qty += tmpl.potential_qty
|
||||
|
||||
@api.multi
|
||||
@api.depends('product_variant_ids.potential_qty')
|
||||
def _get_potential_qty(self):
|
||||
"""Compute the potential as the max of all the variants's potential.
|
||||
|
||||
We can't add the potential of variants: if they share components we
|
||||
may not be able to make all the variants.
|
||||
So we set the arbitrary rule that we can promise up to the biggest
|
||||
variant's potential.
|
||||
"""
|
||||
for tmpl in self:
|
||||
if not tmpl.product_variant_ids:
|
||||
continue
|
||||
tmpl.potential_qty = max(
|
||||
[v.potential_qty for v in tmpl.product_variant_ids])
|
||||
|
||||
@@ -510,7 +510,7 @@ class TestPotentialQty(TransactionCase):
|
||||
self.assertEqual(5.0, p1.potential_qty)
|
||||
|
||||
def test_potential_qty__list(self):
|
||||
# Try to highlight a bug when _get_potential_qty is called on
|
||||
# Try to highlight a bug when _compute_potential_qty is called on
|
||||
# a recordset with multiple products
|
||||
# Recursive compute is not working
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Add the quantity available to promise in the product form -->
|
||||
<record id="view_product_form_potential_qty" model="ir.ui.view">
|
||||
<field name="name">Potential quantity on product form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="stock_available.view_stock_available_form" />
|
||||
<field name="arch" type="xml">
|
||||
<data>
|
||||
<xpath expr="//field[@name='immediately_usable_qty']/ancestor::button" position="after">
|
||||
<button type="action" name="%(stock.product_open_quants)d"
|
||||
attrs="{'invisible':[('type', '!=', 'product')]}"
|
||||
class="oe_stat_button" icon="fa-building-o">
|
||||
<div class="o_form_field o_stat_info">
|
||||
<field name="potential_qty"
|
||||
widget="statinfo" nolabel="1"/>
|
||||
<span class="o_stat_text">Potential</span>
|
||||
</div>
|
||||
</button>
|
||||
</xpath>
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user