mirror of
https://github.com/OCA/stock-logistics-reporting.git
synced 2025-02-16 17:13:21 +02:00
stock_average_daily_sale: Allow to include/exclude weekends
Allow to decide if weekends should be included or excluded in average daily sale calculation.
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
<field name="standard_deviation_exclude_factor">3</field>
|
<field name="standard_deviation_exclude_factor">3</field>
|
||||||
<field name="safety_factor">0.3</field>
|
<field name="safety_factor">0.3</field>
|
||||||
<field name="number_days_qty_in_stock">2</field>
|
<field name="number_days_qty_in_stock">2</field>
|
||||||
|
<field name="exclude_weekends">1</field>
|
||||||
</record>
|
</record>
|
||||||
<record
|
<record
|
||||||
model="stock.average.daily.sale.config"
|
model="stock.average.daily.sale.config"
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
<field name="standard_deviation_exclude_factor">3</field>
|
<field name="standard_deviation_exclude_factor">3</field>
|
||||||
<field name="safety_factor">0.3</field>
|
<field name="safety_factor">0.3</field>
|
||||||
<field name="number_days_qty_in_stock">2</field>
|
<field name="number_days_qty_in_stock">2</field>
|
||||||
|
<field name="exclude_weekends">1</field>
|
||||||
</record>
|
</record>
|
||||||
<record
|
<record
|
||||||
model="stock.average.daily.sale.config"
|
model="stock.average.daily.sale.config"
|
||||||
@@ -34,5 +36,6 @@
|
|||||||
<field name="standard_deviation_exclude_factor">3</field>
|
<field name="standard_deviation_exclude_factor">3</field>
|
||||||
<field name="safety_factor">0.3</field>
|
<field name="safety_factor">0.3</field>
|
||||||
<field name="number_days_qty_in_stock">2</field>
|
<field name="number_days_qty_in_stock">2</field>
|
||||||
|
<field name="exclude_weekends">1</field>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -176,14 +176,16 @@ class StockAverageDailySale(models.Model):
|
|||||||
NOW()::date - '1 day'::interval as date_to,
|
NOW()::date - '1 day'::interval as date_to,
|
||||||
-- start of the analyzed period computed from the original cfg
|
-- start of the analyzed period computed from the original cfg
|
||||||
(NOW() - (period_value::TEXT || ' ' || period_name::TEXT)::INTERVAL):: date as date_from,
|
(NOW() - (period_value::TEXT || ' ' || period_name::TEXT)::INTERVAL):: date as date_from,
|
||||||
-- the number of business days between start and end computed by
|
-- the number of days between start and end computed by
|
||||||
-- removing saturday and sunday
|
-- removing saturday and sunday if weekends should be excluded
|
||||||
(SELECT count(1) from (select EXTRACT(DOW FROM s.d::date) as dd
|
(SELECT count(1) from (select EXTRACT(DOW FROM s.d::date) as dd
|
||||||
FROM generate_series(
|
FROM generate_series(
|
||||||
(NOW() - (period_value::TEXT || ' ' || period_name::TEXT)::INTERVAL):: date ,
|
(NOW() - (period_value::TEXT || ' ' || period_name::TEXT)::INTERVAL):: date ,
|
||||||
(NOW()- '1 day'::interval)::date,
|
(NOW()- '1 day'::interval)::date,
|
||||||
'1 day') AS s(d)) t
|
'1 day') AS s(d)) t
|
||||||
WHERE dd not in(0,6)) AS nrb_days_without_sat_sun
|
WHERE exclude_weekends = False
|
||||||
|
OR (exclude_weekends = True AND dd not in(0,6))
|
||||||
|
) AS nbr_days
|
||||||
FROM
|
FROM
|
||||||
stock_average_daily_sale_config
|
stock_average_daily_sale_config
|
||||||
),
|
),
|
||||||
@@ -209,9 +211,10 @@ class StockAverageDailySale(models.Model):
|
|||||||
+ ( stddev_samp(product_uom_qty) OVER pid * cfg.standard_deviation_exclude_factor)
|
+ ( stddev_samp(product_uom_qty) OVER pid * cfg.standard_deviation_exclude_factor)
|
||||||
) as upper_bound,
|
) as upper_bound,
|
||||||
coalesce ((stddev_samp(product_uom_qty) OVER pid), 0) as standard_deviation,
|
coalesce ((stddev_samp(product_uom_qty) OVER pid), 0) as standard_deviation,
|
||||||
cfg.nrb_days_without_sat_sun,
|
cfg.nbr_days,
|
||||||
cfg.date_from,
|
cfg.date_from,
|
||||||
cfg.date_to,
|
cfg.date_to,
|
||||||
|
cfg.exclude_weekends,
|
||||||
cfg.id as config_id,
|
cfg.id as config_id,
|
||||||
sm.date
|
sm.date
|
||||||
FROM stock_move sm
|
FROM stock_move sm
|
||||||
@@ -239,16 +242,16 @@ class StockAverageDailySale(models.Model):
|
|||||||
)::numeric AS average_qty_by_sale,
|
)::numeric AS average_qty_by_sale,
|
||||||
(count(product_uom_qty) FILTER
|
(count(product_uom_qty) FILTER
|
||||||
(WHERE product_uom_qty BETWEEN lower_bound AND upper_bound OR standard_deviation = 0)
|
(WHERE product_uom_qty BETWEEN lower_bound AND upper_bound OR standard_deviation = 0)
|
||||||
/ nrb_days_without_sat_sun::numeric) AS average_daily_sales_count,
|
/ nbr_days::numeric) AS average_daily_sales_count,
|
||||||
count(product_uom_qty) FILTER
|
count(product_uom_qty) FILTER
|
||||||
(WHERE product_uom_qty BETWEEN lower_bound AND upper_bound OR standard_deviation = 0)::double precision as nbr_sales,
|
(WHERE product_uom_qty BETWEEN lower_bound AND upper_bound OR standard_deviation = 0)::double precision as nbr_sales,
|
||||||
standard_deviation::numeric ,
|
standard_deviation::numeric ,
|
||||||
date_from,
|
date_from,
|
||||||
date_to,
|
date_to,
|
||||||
config_id,
|
config_id,
|
||||||
nrb_days_without_sat_sun
|
nbr_days
|
||||||
FROM deliveries_last
|
FROM deliveries_last
|
||||||
GROUP BY product_id, warehouse_id, standard_deviation, nrb_days_without_sat_sun, date_from, date_to, config_id
|
GROUP BY product_id, warehouse_id, standard_deviation, nbr_days, date_from, date_to, config_id
|
||||||
),
|
),
|
||||||
-- Compute the stock by product in locations under stock
|
-- Compute the stock by product in locations under stock
|
||||||
stock_qty AS (
|
stock_qty AS (
|
||||||
@@ -262,7 +265,6 @@ class StockAverageDailySale(models.Model):
|
|||||||
GROUP BY sq.product_id, sl.warehouse_id
|
GROUP BY sq.product_id, sl.warehouse_id
|
||||||
),
|
),
|
||||||
-- Compute the standard deviation of the average daily sales count
|
-- Compute the standard deviation of the average daily sales count
|
||||||
-- excluding saturday and sunday
|
|
||||||
daily_standard_deviation AS(
|
daily_standard_deviation AS(
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
@@ -279,7 +281,7 @@ class StockAverageDailySale(models.Model):
|
|||||||
(WHERE product_uom_qty BETWEEN lower_bound AND upper_bound OR standard_deviation = 0)
|
(WHERE product_uom_qty BETWEEN lower_bound AND upper_bound OR standard_deviation = 0)
|
||||||
) as daily_sales
|
) as daily_sales
|
||||||
FROM deliveries_last
|
FROM deliveries_last
|
||||||
WHERE EXTRACT(DOW FROM date) <> '0' AND EXTRACT(DOW FROM date) <> '6'
|
WHERE exclude_weekends = False OR (EXTRACT(DOW FROM date) <> '0' AND EXTRACT(DOW FROM date) <> '6')
|
||||||
GROUP BY product_id, warehouse_id, 1
|
GROUP BY product_id, warehouse_id, 1
|
||||||
) as averages_daily group by id, product_id, warehouse_id
|
) as averages_daily group by id, product_id, warehouse_id
|
||||||
|
|
||||||
@@ -303,11 +305,11 @@ class StockAverageDailySale(models.Model):
|
|||||||
is_mto,
|
is_mto,
|
||||||
sqty.qty_in_stock as qty_in_stock,
|
sqty.qty_in_stock as qty_in_stock,
|
||||||
ds.daily_standard_deviation,
|
ds.daily_standard_deviation,
|
||||||
ds.daily_standard_deviation * cfg.safety_factor * sqrt(nrb_days_without_sat_sun) as safety,
|
ds.daily_standard_deviation * cfg.safety_factor * sqrt(nbr_days) as safety,
|
||||||
(cfg.number_days_qty_in_stock * average_qty_by_sale * average_daily_sales_count) + (ds.daily_standard_deviation * cfg.safety_factor * sqrt(nrb_days_without_sat_sun)) as safety_bin_min_qty_new,
|
(cfg.number_days_qty_in_stock * average_qty_by_sale * average_daily_sales_count) + (ds.daily_standard_deviation * cfg.safety_factor * sqrt(nbr_days)) as safety_bin_min_qty_new,
|
||||||
cfg.number_days_qty_in_stock * GREATEST(average_daily_sales_count, 1) * (average_qty_by_sale + (standard_deviation * cfg.safety_factor)) as safety_bin_min_qty_old,
|
cfg.number_days_qty_in_stock * GREATEST(average_daily_sales_count, 1) * (average_qty_by_sale + (standard_deviation * cfg.safety_factor)) as safety_bin_min_qty_old,
|
||||||
GREATEST(
|
GREATEST(
|
||||||
(cfg.number_days_qty_in_stock * average_qty_by_sale * average_daily_sales_count) + (ds.daily_standard_deviation * cfg.safety_factor * sqrt(nrb_days_without_sat_sun)),
|
(cfg.number_days_qty_in_stock * average_qty_by_sale * average_daily_sales_count) + (ds.daily_standard_deviation * cfg.safety_factor * sqrt(nbr_days)),
|
||||||
(cfg.number_days_qty_in_stock * average_qty_by_sale)
|
(cfg.number_days_qty_in_stock * average_qty_by_sale)
|
||||||
) as recommended_qty
|
) as recommended_qty
|
||||||
FROM averages t
|
FROM averages t
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ class StockAverageDailySaleConfig(models.Model):
|
|||||||
),
|
),
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
|
exclude_weekends = fields.Boolean(
|
||||||
|
string="Exclude Weekends",
|
||||||
|
help="Set to True only if you do not expect any orders/deliveries during "
|
||||||
|
"the weekends. If set to True, stock moves done on weekends won't be "
|
||||||
|
"taken into account to calculate the average daily usage",
|
||||||
|
)
|
||||||
period_name = fields.Selection(
|
period_name = fields.Selection(
|
||||||
string="Period analyzed unit",
|
string="Period analyzed unit",
|
||||||
selection=[
|
selection=[
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree editable="top" create="false" delete="false">
|
<tree editable="top" create="false" delete="false">
|
||||||
<field name="abc_classification_level" />
|
<field name="abc_classification_level" />
|
||||||
|
<field name="exclude_weekends" />
|
||||||
<field name="period_value" />
|
<field name="period_value" />
|
||||||
<field name="period_name" />
|
<field name="period_name" />
|
||||||
<field name="number_days_qty_in_stock" />
|
<field name="number_days_qty_in_stock" />
|
||||||
|
|||||||
Reference in New Issue
Block a user