Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions product_stock_state/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

{
"name": "Product Stock State",
"summary": "Compute the state of a product's stock"
"the stock level and sale_ok field",
"summary": """Compute the state of a product's stock
Offers 'sale ok' field
Tracks the stock level and manage the following product's stock states based on rules :
'on demand' 'in_stock' 'limited stock' 'resupplying' 'out of stock'
""",
"version": "14.0.1.0.1",
"website": "https://github.com/OCA/product-attribute",
"author": " Akretion, GRAP, Odoo Community Association (OCA)",
Expand Down
17 changes: 17 additions & 0 deletions product_stock_state/i18n/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ msgstr ""
msgid "Manual Stock State Threshold"
msgstr "Seuil pour l'état du stock manuel"

#. module: product_stock_state
#: model:ir.model.fields,field_description:product_stock_state.field_product_product__on_demand
#: model:ir.model.fields,field_description:product_stock_state.field_product_template__on_demand
msgid "On Demand"
msgstr "Sur demande"

#. module: product_stock_state
#: model:ir.model.fields,help:product_stock_state.field_product_template_on_demand
msgid "This field allows you to force the stock state to the on-demand value"
msgstr "Ce champ vous permet de forcer l'état du stock à 'À la demande'"

#. module: product_stock_state
#: model:ir.model,name:product_stock_state.model_product_product
msgid "Product"
Expand Down Expand Up @@ -174,6 +185,12 @@ msgstr ""
"elle n'est pas définie, Odoo utilisera le seuil défini au niveau de "
"l'entreprise."

#. module: product_stock_state
#: model:ir.model.fields,help:product_stock_state.field_product_product__on_demand
#: model:ir.model.fields,help:product_stock_state.field_product_template__on_demand
msgid "This field allows you to force the stock state to the on-demand value"
msgstr "Ce champs vous permet de forcer l'état du stock à 'A la demande'"

#. module: product_stock_state
#: model:product.product,uom_name:product_stock_state.product_setting_by_company
#: model:product.product,uom_name:product_stock_state.product_setting_by_product
Expand Down
11 changes: 11 additions & 0 deletions product_stock_state/i18n/product_stock_state.pot
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ msgstr ""
msgid "Manual Stock State Threshold"
msgstr ""

#. module: product_stock_state
#: model:ir.model.fields,field_description:product_stock_state.field_product_product__on_demand
#: model:ir.model.fields,field_description:product_stock_state.field_product_template__on_demand
msgid "On Demand"
msgstr ""

#. module: product_stock_state
#: model:ir.model.fields,help:product_stock_state.field_product_template__on_demand
msgid "This field allows you to force the stock state to the on-demand value"
msgstr ""

#. module: product_stock_state
#: model:ir.model,name:product_stock_state.model_product_product
msgid "Product"
Expand Down
10 changes: 10 additions & 0 deletions product_stock_state/models/product_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ProductProduct(models.Model):
_inherit = "product.product"

_STOCK_STATE_SELECTION = [
("on_demand", "On Demand"),
("in_stock", "In Stock"),
("in_limited_stock", "In Limited Stock"),
("resupplying", "Resupplying"),
Expand Down Expand Up @@ -57,6 +58,9 @@ def _stock_state_check_resupplying(self, qty, precision):
def _stock_state_check_out_of_stock(self, qty, precision):
return True

def _stock_state_check_on_demand(self, qty, precision):
return self.on_demand

def _available_states(self):
return [x[0] for x in self._selection_stock_state()]

Expand All @@ -65,8 +69,14 @@ def _available_states(self):
"incoming_qty",
"stock_state_threshold",
"company_id.stock_state_threshold",
"on_demand",
)
def _compute_stock_state(self):
"""
This method updates {stock_state} of each triggered {product}.
{stock_state} = first {state} where {product}_stock_state_check_{state} is True
{state} ordering is insured by _available_states method
"""
precision = self.env["decimal.precision"].precision_get("Stock Threshold")
for product in self:
qty_available = product._get_qty_available_for_stock_state()
Expand Down
5 changes: 5 additions & 0 deletions product_stock_state/models/product_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class ProductTemplate(models.Model):

manual_stock_state_threshold = fields.Float(digits="Stock Threshold")

on_demand = fields.Boolean(
default=False,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that by default we get False value for Boolean fields

@mpvphd mpvphd Feb 20, 2025

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True !
in the end this is useless but harmless piece of code too ^^
thx

help="This field allows you to force the stock state to the on-demand value"
)

@api.depends("categ_id.stock_state_threshold", "manual_stock_state_threshold")
def _compute_stock_state_threshold(self):
for rec in self:
Expand Down
25 changes: 25 additions & 0 deletions product_stock_state/tests/test_product_stock_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,28 @@ def test_04_category_setting_inherit(self):
def test_05_state_out_of_stock(self):
"""Test Stock State computation"""
self.assertEqual(self.product_threshold_on_product.stock_state, "out_of_stock")

# on_demand tests

def test_06_state_on_demand_default_value(self):
"""Test default value of on_demand"""
self.assertFalse(self.product_threshold_on_product.on_demand)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless test


def test_07_on_demand_inherit(self):
"""Test on_demand Setting (Setting on a product unique template)"""
self.assertEqual(
self.product_threshold_on_product._stock_state_check_on_demand(),
self.product_threshold_on_product.on_demand,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useless

)

def test_08_state_on_demand_computation(self):
"""Test on_demand = True Stock State computation
stock_state is set to 'on_demand' regardless of the previous state"""

self.product_threshold_on_product.on_demand = True
states = self.product_threshold_on_product._available_states()

for state in states:
self.product_threshold_on_product.stock_state = state
self.product_threshold_on_product._compute_stock_state()
self.assertEqual(self.product_threshold_on_product.stock_state, 'on_demand')
14 changes: 11 additions & 3 deletions product_stock_state/views/product_template_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,18 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="stock.view_template_property_form" />
<field name="arch" type="xml">

<xpath expr="//div[@name='options']" position="after">
<div>
<field name="on_demand"/>
<label for="on_demand"/>
</div>
</xpath>

<xpath expr="//group[@name='group_lots_and_weight']" position="after">
<group name="treshold" string="Stock Threshold">
<field name="stock_state_threshold" />
<field name="manual_stock_state_threshold" class="oe_edit_only" />
<group name="treshold" string="Stock threshold" attrs="{'invisible': [('on_demand', '=', True)]}">
<field name="stock_state_threshold"/>
<field name="manual_stock_state_threshold" class="oe_edit_only"/>
</group>
</xpath>
</field>
Expand Down