vendor_delay_report.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo import api, fields, models, tools
  4. from odoo.exceptions import UserError
  5. from odoo.osv.expression import expression
  6. class VendorDelayReport(models.Model):
  7. _name = "vendor.delay.report"
  8. _description = "Vendor Delay Report"
  9. _auto = False
  10. partner_id = fields.Many2one('res.partner', 'Vendor', readonly=True)
  11. product_id = fields.Many2one('product.product', 'Product', readonly=True)
  12. category_id = fields.Many2one('product.category', 'Product Category', readonly=True)
  13. date = fields.Datetime('Effective Date', readonly=True)
  14. qty_total = fields.Float('Total Quantity', readonly=True)
  15. qty_on_time = fields.Float('On-Time Quantity', readonly=True)
  16. on_time_rate = fields.Float('On-Time Delivery Rate', readonly=True)
  17. def init(self):
  18. tools.drop_view_if_exists(self.env.cr, 'vendor_delay_report')
  19. self.env.cr.execute("""
  20. CREATE OR replace VIEW vendor_delay_report AS(
  21. SELECT m.id AS id,
  22. m.date AS date,
  23. m.purchase_line_id AS purchase_line_id,
  24. m.product_id AS product_id,
  25. Min(pc.id) AS category_id,
  26. Min(po.partner_id) AS partner_id,
  27. Min(m.product_qty) AS qty_total,
  28. Sum(CASE
  29. WHEN (m.state = 'done' and pol.date_planned::date >= m.date::date) THEN (ml.qty_done / ml_uom.factor * pt_uom.factor)
  30. ELSE 0
  31. END) AS qty_on_time
  32. FROM stock_move m
  33. JOIN purchase_order_line pol
  34. ON pol.id = m.purchase_line_id
  35. JOIN purchase_order po
  36. ON po.id = pol.order_id
  37. JOIN product_product p
  38. ON p.id = m.product_id
  39. JOIN product_template pt
  40. ON pt.id = p.product_tmpl_id
  41. JOIN uom_uom pt_uom
  42. ON pt_uom.id = pt.uom_id
  43. JOIN product_category pc
  44. ON pc.id = pt.categ_id
  45. LEFT JOIN stock_move_line ml
  46. ON ml.move_id = m.id
  47. LEFT JOIN uom_uom ml_uom
  48. ON ml_uom.id = ml.product_uom_id
  49. GROUP BY m.id
  50. )""")
  51. @api.model
  52. def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
  53. if all('on_time_rate' not in field for field in fields):
  54. res = super().read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
  55. return res
  56. for field in fields:
  57. if 'on_time_rate' not in field:
  58. continue
  59. fields.remove(field)
  60. agg = field.split(':')[1:]
  61. if agg and agg[0] != 'sum':
  62. raise NotImplementedError('Aggregate functions other than \':sum\' are not allowed.')
  63. qty_total = field.replace('on_time_rate', 'qty_total')
  64. if qty_total not in fields:
  65. fields.append(qty_total)
  66. qty_on_time = field.replace('on_time_rate', 'qty_on_time')
  67. if qty_on_time not in fields:
  68. fields.append(qty_on_time)
  69. break
  70. res = super().read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)
  71. for group in res:
  72. if group['qty_total'] == 0:
  73. on_time_rate = 100
  74. else:
  75. on_time_rate = group['qty_on_time'] / group['qty_total'] * 100
  76. group.update({'on_time_rate': on_time_rate})
  77. return res