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.
 
 
 
 
 

98 lines
3.7 KiB

# Copyright 2020 Coop IT Easy SCRL fs
# Robin Keunen <robin@coopiteasy.be>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class ProductTemplate(models.Model):
_inherit = "product.template"
@api.multi
@api.constrains("computation_range")
def _check_computation_range(self):
for template in self:
if template.computation_range <= 0:
raise ValidationError(
_("Computation range must be greater than 0.")
)
computation_range = fields.Integer("Computation range (days)", default=14)
range_sales = fields.Float(
string="Sales over Range",
compute="_compute_stock_coverage",
store=True,
)
daily_sales = fields.Float(
string="Daily Sales", compute="_compute_stock_coverage", store=True
)
stock_coverage = fields.Float(
string="Stock Coverage (days)",
compute="_compute_stock_coverage",
store=True,
)
effective_sale_price = fields.Float(
string="Effective Sale Price",
compute="_compute_stock_coverage",
store=True,
help="SUM (total sale price without vat / sold quantity ) "
"/ count (pos order line)",
)
@api.multi
@api.depends("computation_range", "virtual_available", "active")
def _compute_stock_coverage(self):
query = """
select template.id as product_template_id,
sum(pol.qty) as total_sales,
sum(pol.qty) / template.computation_range as daily_sales,
sum(pol.price_subtotal / pol.qty) /
count(pol.id) as effective_sale_price,
sum(pol.price_subtotal_incl / pol.qty) /
count(pol.id) as effective_sale_price_incl
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 po.date_order
BETWEEN now() - template.computation_range * interval '1 days'
and now()
and pol.qty != 0
and template.id in %(template_ids)s
group by product_template_id
"""
if self.ids: # on RecordSet
template_ids = tuple(self.ids)
elif self._origin: # on temporary object (on_change)
template_ids = (self._origin.id,)
else: # on temporary object (creation)
return True
self.env.cr.execute(query, {"template_ids": template_ids})
results = {
pid: (qty, avg, esp, espi)
for pid, qty, avg, esp, espi in self.env.cr.fetchall()
}
for template in self:
qty, avg, esp, espi = results.get(template.id, (0, 0, 0, 0))
template.range_sales = qty
template.daily_sales = avg
if any(template.taxes_id.mapped("price_include")):
template.effective_sale_price = espi
else:
template.effective_sale_price = esp
if avg != 0:
template.stock_coverage = template.virtual_available / avg
else:
template.stock_coverage = 9999
@api.model
def cron_compute_stock_coverage(self):
templates = self.env["product.template"].search([])
templates._compute_stock_coverage()