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.
125 lines
4.1 KiB
125 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)
|