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.

65 lines
2.4 KiB

4 years ago
  1. # Copyright 2020 Coop IT Easy SCRL fs
  2. # Robin Keunen <robin@coopiteasy.be>
  3. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  4. from odoo import _, api, fields, models
  5. from odoo.exceptions import ValidationError
  6. class ProductTemplate(models.Model):
  7. _inherit = "product.template"
  8. @api.multi
  9. @api.constrains("computation_range")
  10. def _check_computation_range(self):
  11. for template in self:
  12. if template.computation_range <= 0:
  13. raise ValidationError(
  14. _("Computation range must be greater than 0.")
  15. )
  16. computation_range = fields.Integer("Computation range (days)", default=14)
  17. range_sales = fields.Float(
  18. string="Sales over Range", compute="_compute_stock_coverage"
  19. )
  20. daily_sales = fields.Float(
  21. string="Daily Sales", compute="_compute_stock_coverage"
  22. )
  23. stock_coverage = fields.Float(
  24. string="Stock Coverage (days)", compute="_compute_stock_coverage"
  25. )
  26. @api.multi
  27. def _compute_stock_coverage(self):
  28. query = """
  29. select template.id as product_template_id,
  30. sum(pol.qty) as total_sales,
  31. sum(pol.qty) / template.computation_range as daily_sales
  32. from pos_order_line pol
  33. join pos_order po ON pol.order_id = po.id
  34. join product_product product ON pol.product_id = product.id
  35. join product_template template
  36. ON product.product_tmpl_id = template.id
  37. where po.state in ('done', 'invoiced', 'paid')
  38. and template.active
  39. and po.date_order
  40. BETWEEN now() - template.computation_range * interval '1 days'
  41. and now()
  42. and template.id in %(template_ids)s
  43. group by product_template_id
  44. """
  45. self.env.cr.execute(query, {"template_ids": tuple(self.ids)})
  46. results = {pid: (qty, avg) for pid, qty, avg in self.env.cr.fetchall()}
  47. for template in self:
  48. qty, avg = results.get(template.id, (0, 0))
  49. template.range_sales = qty
  50. template.daily_sales = avg
  51. if avg != 0:
  52. template.stock_coverage = template.virtual_available / avg
  53. else:
  54. template.stock_coverage = 9999
  55. @api.model
  56. def cron_compute_stock_coverage(self):
  57. templates = self.env["product.template"].search([])
  58. templates._compute_stock_coverage()