[IMP] stock_average_daily_sale: Store the configurations on profile level + add demo

The configurations are now stored on abc profiles.

Some demo data are loaded in order to show this module features more easily.
This commit is contained in:
Denis Roussel
2023-02-14 14:50:33 +01:00
committed by twalter-c2c
parent 35310da0bc
commit bc6e262a84
12 changed files with 178 additions and 1 deletions

View File

@@ -1 +1 @@
from . import models
from . import models, wizards

View File

@@ -13,18 +13,23 @@
"sale",
"stock_storage_type_putaway_abc",
"product_abc_classification",
"product_abc_classification_sale_stock",
"product_route_mto",
"stock_location_zone",
],
"data": [
"security/stock_average_daily_sale_config.xml",
"security/stock_average_daily_sale.xml",
"security/stock_average_daily_sale_demo.xml",
"views/stock_average_daily_sale_config.xml",
"views/stock_average_daily_sale.xml",
"views/abc_classification_profile.xml",
"views/stock_warehouse.xml",
"data/ir_cron.xml",
],
"external_dependencies": {"python": ["freezegun"]},
"demo": [
"demo/stock_average_daily_sale_config.xml",
"demo/stock_move.xml",
],
}

View File

@@ -6,6 +6,10 @@
model="stock.average.daily.sale.config"
id="stock_average_daily_sale_config_level_a"
>
<field
name="abc_classification_profile_id"
ref="product_abc_classification_sale_stock.abc_classification_profile_sale_stock"
/>
<field name="abc_classification_level">a</field>
<field name="period_value">2</field>
<field name="period_name">week</field>
@@ -17,6 +21,10 @@
model="stock.average.daily.sale.config"
id="stock_average_daily_sale_config_level_b"
>
<field
name="abc_classification_profile_id"
ref="product_abc_classification_sale_stock.abc_classification_profile_sale_stock"
/>
<field name="abc_classification_level">b</field>
<field name="period_value">13</field>
<field name="period_name">week</field>
@@ -28,6 +36,10 @@
model="stock.average.daily.sale.config"
id="stock_average_daily_sale_config_level_c"
>
<field
name="abc_classification_profile_id"
ref="product_abc_classification_sale_stock.abc_classification_profile_sale_stock"
/>
<field name="abc_classification_level">c</field>
<field name="period_value">26</field>
<field name="period_name">week</field>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2023 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo noupdate="1">
<function model="stock.average.daily.sale.demo" name="_action_create_data" />
</odoo>

View File

@@ -1,3 +1,4 @@
from . import stock_warehouse # isort:skip
from . import stock_average_daily_sale_config # isort:skip
from . import stock_average_daily_sale # isort:skip
from . import abc_classification_profile

View File

@@ -0,0 +1,15 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class AbcClassificationProfile(models.Model):
_inherit = "abc.classification.profile"
stock_average_daily_sale_config_ids = fields.One2many(
comodel_name="stock.average.daily.sale.config",
inverse_name="abc_classification_profile_id",
string="Average Daily Sale Configurations",
)

View File

@@ -22,6 +22,11 @@ class StockAverageDailySale(models.Model):
_order = "abc_classification_level ASC, product_id ASC"
_description = "Average Daily Sale for Products"
abc_classification_profile_id = fields.Many2one(
comodel_name="abc.classification.profile",
required=True,
index=True,
)
abc_classification_level = fields.Selection(
selection=ABC_SELECTION, required=True, readonly=True, index=True
)
@@ -282,6 +287,7 @@ class StockAverageDailySale(models.Model):
date_to,
config_id,
abc_classification_level,
cfg.abc_classification_profile_id,
sale_ok,
is_mto,
sqty.qty_in_stock as qty_in_stock,

View File

@@ -13,6 +13,11 @@ class StockAverageDailySaleConfig(models.Model):
_name = "stock.average.daily.sale.config"
_description = "Average daily sales computation parameters"
abc_classification_profile_id = fields.Many2one(
comodel_name="abc.classification.profile",
required=True,
ondelete="cascade",
)
abc_classification_level = fields.Selection(
selection=ABC_SELECTION, required=True, readonly=True
)

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2021 ACSONE SA/NV
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.model.access" id="stock_average_daily_sale_demo_access_user">
<field name="name">stock.average.daily.sale.demo access user</field>
<field name="model_id" ref="model_stock_average_daily_sale_demo" />
<field name="group_id" ref="base.group_user" />
<field name="perm_read" eval="1" />
<field name="perm_create" eval="0" />
<field name="perm_write" eval="0" />
<field name="perm_unlink" eval="0" />
</record>
</odoo>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Copyright 2023 ACSONE SA/NV
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="abc_classification_profile_form_view" model="ir.ui.view">
<field
name="name"
>abc.classification.profile.form (in stock_average_daily_sale)</field>
<field name="model">abc.classification.profile</field>
<field
name="inherit_id"
ref="product_abc_classification.abc_classification_profile_form_view"
/>
<field name="arch" type="xml">
<field name="level_ids" position="after">
<field name="stock_average_daily_sale_config_ids" />
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
from . import stock_average_daily_sale_demo

View File

@@ -0,0 +1,91 @@
# Copyright 2023 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
from dateutil.relativedelta import relativedelta
from freezegun import freeze_time
from odoo import _, api, models
from odoo.fields import Date, Datetime
_logger = logging.getLogger(__name__)
class StockAverageDailySaleDemo(models.TransientModel):
_name = "stock.average.daily.sale.demo"
_description = "Wizard to populate demo data with past moves for Average Daily Sale"
def _create_move(self, product, origin_location, qty):
suppliers = self.env.ref("stock.stock_location_suppliers")
customers = self.env.ref("stock.stock_location_customers")
move_obj = self.env["stock.move"]
# Create first an incoming move to avoid negative quantities
move = move_obj.create(
{
"product_id": product.id,
"name": product.name,
"location_id": suppliers.id,
"location_dest_id": customers.id,
"product_uom_qty": qty,
}
)
move._action_confirm()
move._action_assign()
move.quantity_done = move.product_uom_qty
move._action_done()
# Create the OUT move
move = move_obj.create(
{
"product_id": product.id,
"name": product.name,
"location_id": origin_location.id,
"location_dest_id": customers.id,
"product_uom_qty": qty,
"priority": "1",
}
)
return move
@api.model
def _create_movement(self, product):
now = Datetime.now()
stock = self.env.ref("stock.stock_location_stock")
move_1_date = Date.to_string(now - relativedelta(weeks=11))
with freeze_time(move_1_date):
move = self._create_move(product, stock, 10.0)
move._action_confirm()
move._action_assign()
move.quantity_done = move.product_uom_qty
move._action_done()
move.priority = "1"
move_2_date = Date.to_string(now - relativedelta(weeks=9))
with freeze_time(move_2_date):
move = self._create_move(product, stock, 12.0)
move._action_confirm()
move._action_assign()
move.quantity_done = move.product_uom_qty
move._action_done()
move.priority = "1"
@api.model
def _action_create_data(self):
"""
This is called through an xml function in order to populate
demo data with past moves as the report depends on that.
"""
module = self.env["ir.module.module"].search(
[("name", "=", "stock_average_daily_sale"), ("demo", "=", True)]
)
if not module:
_logger.warning(
_("You cannot call the _action_create_data() on production database.")
)
return
product = self.env.ref("product.product_product_25")
self._create_movement(product)
product = self.env.ref("product.product_product_27")
self._create_movement(product)
self.env["stock.average.daily.sale"].refresh_view()