You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
4.1 KiB
126 lines
4.1 KiB
# -*- encoding: utf-8 -*-
|
|
from openerp import models, fields, api
|
|
import datetime as dt
|
|
|
|
|
|
class ProductTemplate(models.Model):
|
|
_inherit = "product.template"
|
|
|
|
consumption_calculation_method = fields.Selection(
|
|
selection=[("sales_history", "Sales History")],
|
|
string="Consumption Calculation Method",
|
|
default="sales_history",
|
|
)
|
|
calculation_range = fields.Integer("Calculation range (days)", default=14)
|
|
|
|
average_consumption = fields.Float(
|
|
string="Average Consumption",
|
|
compute="_compute_average_daily_consumption",
|
|
readonly=True,
|
|
digits=(100, 2),
|
|
)
|
|
|
|
total_consumption = fields.Float(
|
|
string="Total Consumption",
|
|
default=0,
|
|
compute="_compute_total_consumption",
|
|
store=True,
|
|
readonly=True,
|
|
digits=(100, 2),
|
|
)
|
|
|
|
estimated_stock_coverage = fields.Float(
|
|
string="Estimated Stock Coverage (days)",
|
|
compute="_compute_estimated_stock_coverage",
|
|
default=0,
|
|
digits=(100, 2),
|
|
readonly=True,
|
|
)
|
|
|
|
@api.multi
|
|
@api.depends("total_consumption")
|
|
def _compute_average_daily_consumption(self):
|
|
for template in self:
|
|
if template.calculation_range > 0:
|
|
avg = template.total_consumption / template.calculation_range
|
|
else:
|
|
avg = 0
|
|
template.average_consumption = avg
|
|
|
|
return True
|
|
|
|
@api.multi
|
|
@api.depends("calculation_range")
|
|
def _compute_total_consumption(self):
|
|
for template in self:
|
|
products = self.env["product.product"].search(
|
|
[("product_tmpl_id", "=", template.id)]
|
|
)
|
|
|
|
today = dt.date.today()
|
|
pol_date_limit = today - dt.timedelta(
|
|
days=template.calculation_range
|
|
)
|
|
|
|
order_lines = self.env["pos.order.line"].search(
|
|
[
|
|
("product_id", "in", products.ids),
|
|
(
|
|
"create_date",
|
|
">",
|
|
fields.Datetime.to_string(pol_date_limit),
|
|
), # noqa
|
|
]
|
|
)
|
|
|
|
if order_lines:
|
|
order_lines = order_lines.filtered(
|
|
lambda ol: ol.order_id.state
|
|
in ["done", "invoiced", "paid"]
|
|
) # noqa
|
|
template.total_consumption = sum(order_lines.mapped("qty"))
|
|
else:
|
|
template.total_consumption = 0
|
|
return True
|
|
|
|
@api.multi
|
|
@api.depends("total_consumption")
|
|
def _compute_estimated_stock_coverage(self):
|
|
for product_template in self:
|
|
qty = product_template.qty_available
|
|
avg = product_template.average_consumption
|
|
if avg > 0:
|
|
product_template.estimated_stock_coverage = qty / avg
|
|
else:
|
|
# todo what would be a good default value? (not float(inf))
|
|
product_template.estimated_stock_coverage = 9999
|
|
|
|
return True
|
|
|
|
@api.model
|
|
def _batch_compute_total_consumption(self):
|
|
products = self.env["product.template"].search([("active", "=", True)])
|
|
|
|
query = """
|
|
select
|
|
template.id as product_template_id,
|
|
sum(pol.qty) as total_consumption
|
|
from pos_order_line pol
|
|
join pos_order po ON pol.order_id = po.id
|
|
join product_product product ON pol.product_id = product.id
|
|
join product_template template ON product.product_tmpl_id = template.id
|
|
where po.state in ('done', 'invoiced', 'paid')
|
|
and template.active
|
|
and pol.create_date
|
|
BETWEEN date_trunc('day', now()) - calculation_range * interval '1 days'
|
|
and date_trunc('day', now())
|
|
group by product_template_id
|
|
""" # noqa
|
|
|
|
self.env.cr.execute(query)
|
|
results = {pid: qty for pid, qty in self.env.cr.fetchall()}
|
|
|
|
for product in products:
|
|
product.total_consumption = results.get(
|
|
product.id, product.total_consumption
|
|
)
|