GoodERP
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.

171 lines
8.1KB

  1. from odoo import models, fields, api
  2. from datetime import datetime
  3. import pytz
  4. from lxml import etree
  5. class NonActiveReport(models.TransientModel):
  6. _name = 'non.active.report'
  7. _description = '库龄报表'
  8. warehouse_id = fields.Many2one('warehouse', string='仓库')
  9. goods_id = fields.Many2one('goods', string='商品')
  10. attribute_id = fields.Many2one('attribute', string='属性')
  11. first_stage_day_qty = fields.Float(string='第一阶段数量')
  12. second_stage_day_qty = fields.Float(string='第二阶段数量')
  13. third_stage_day_qty = fields.Float(string='第三阶段数量')
  14. four_stage_day_qty = fields.Float(string='第四阶段数量')
  15. subtotal = fields.Float('合计')
  16. latest_move_date = fields.Datetime('最后发货日期')
  17. latest_move_qty = fields.Float('最后发货数量')
  18. @api.model
  19. def get_view(self, view_id=None, view_type='form', **options):
  20. """
  21. 继承系统自带的 视图构造方法 fields_view_get 实现动态的修改 呆滞报表的表头 string动态
  22. :param view_id:
  23. :param toolbar:
  24. :param submenu:
  25. :return:
  26. """
  27. res = super().get_view(view_id, view_type, **options)
  28. if self._context.get('first_stage_day'):
  29. now_date = datetime.strftime(
  30. datetime.now(pytz.timezone("UTC")), '%Y-%m-%d')
  31. doc = etree.XML(res['arch'])
  32. for node in doc.xpath("//field[@name='first_stage_day_qty']"):
  33. node.set('string', u"0~%s天" %
  34. (self._context.get('first_stage_day')))
  35. for node in doc.xpath("//field[@name='second_stage_day_qty']"):
  36. node.set('string',
  37. u"%s天~%s天" % (self._context.get('first_stage_day'), self._context.get('second_stage_day')))
  38. for node in doc.xpath("//field[@name='third_stage_day_qty']"):
  39. node.set('string',
  40. u"%s天~%s天" % (self._context.get('second_stage_day'), self._context.get('third_stage_day')))
  41. for node in doc.xpath("//field[@name='four_stage_day_qty']"):
  42. node.set('string', u"大于%s天" %
  43. (self._context.get('third_stage_day')))
  44. res['arch'] = etree.tostring(doc)
  45. return res
  46. class NonActiveReportWizard(models.TransientModel):
  47. _name = 'non.active.report.wizard'
  48. _description = '库龄报表向导'
  49. warehouse_id = fields.Many2one('warehouse', string='仓库')
  50. first_stage_day = fields.Integer(string='第一阶段天数', required=True)
  51. second_stage_day = fields.Integer(string='第二阶段天数', required=True)
  52. third_stage_day = fields.Integer(string='第三阶段天数', required=True)
  53. company_id = fields.Many2one(
  54. 'res.company',
  55. string='公司',
  56. change_default=True,
  57. default=lambda self: self.env.company)
  58. def get_warehouse_goods_stage_data(self, warehouse_id, first_stage_day, second_stage_day, third_stage_day):
  59. """
  60. 用sql 找到 系统 在所输入的时间阶段的对应的商品的 数量
  61. :param warehouse_id: 仓库id
  62. :param first_stage_day: 第一阶段天数
  63. :param second_stage_day:第一阶段天数
  64. :param third_stage_day: 第三阶段天数
  65. :return: 返回list dict
  66. """
  67. if warehouse_id:
  68. wahouse_id_sql = "AND wh_dest.id =%s" % (warehouse_id.id)
  69. else:
  70. wahouse_id_sql = "AND 1=1"
  71. now_date = datetime.strftime(
  72. datetime.now(pytz.timezone("UTC")), '%Y-%m-%d')
  73. vals = {'now_date': now_date, 'first_stage_day': first_stage_day, 'wahouse_id_sql': wahouse_id_sql,
  74. 'second_stage_day': second_stage_day, 'third_stage_day': third_stage_day}
  75. self.env.cr.execute('''
  76. select
  77. stage_goods_date.warehouse_dest_id as warehouse_id,
  78. stage_goods_date.goods_id as goods_id,
  79. stage_goods_date.attribute_id as attribute_id,
  80. NULL as latest_move_date,
  81. NULL as latest_move_qty,
  82. COALESCE(sum(stage_goods_date.first_stage),0) as first_stage_day_qty,
  83. COALESCE(sum(stage_goods_date.second_stage),0) as second_stage_day_qty,
  84. COALESCE(sum(stage_goods_date.third_stage),0) as third_stage_day_qty,
  85. COALESCE(sum(stage_goods_date.four_stage),0) as four_stage_day_qty,
  86. sum(stage_goods_date.subtotal) as subtotal
  87. from (select
  88. CASE
  89. when ('%(now_date)s' -line.date<=%(first_stage_day)d) then
  90. sum(line.qty_remaining)
  91. end as first_stage,
  92. CASE
  93. when ('%(now_date)s'-line.date>%(first_stage_day)d and '%(now_date)s' -line.date<=%(second_stage_day)d) then
  94. sum(line.qty_remaining)
  95. end as second_stage,
  96. CASE
  97. when ('%(now_date)s' -line.date>%(second_stage_day)d AND '%(now_date)s'-line.date<=%(third_stage_day)d) then
  98. sum(line.qty_remaining)
  99. end as third_stage,
  100. CASE
  101. when ('%(now_date)s'-line.date > %(third_stage_day)d) then
  102. sum(line.qty_remaining)
  103. end as four_stage,
  104. line.goods_id as goods_id,
  105. line.attribute_id as attribute_id,
  106. line.warehouse_dest_id as warehouse_dest_id,
  107. sum(line.qty_remaining) as subtotal
  108. FROM wh_move_line line
  109. LEFT JOIN warehouse wh_dest ON line.warehouse_dest_id = wh_dest.id
  110. LEFT JOIN warehouse wh ON line.warehouse_id = wh.id
  111. where line.state = 'done'
  112. %(wahouse_id_sql)s
  113. AND wh_dest.type='stock'
  114. GROUP BY line.warehouse_dest_id,line.goods_id,line.attribute_id,line.date) as stage_goods_date
  115. GROUP BY stage_goods_date.warehouse_dest_id,stage_goods_date.goods_id,stage_goods_date.attribute_id
  116. ''' % vals)
  117. return self.env.cr.dictfetchall()
  118. def open_non_active_report(self):
  119. """
  120. :return:
  121. 返回生成好的 库龄报表 记录的list视图返回,让用户可以直接看到结果
  122. """
  123. data_vals_list = self.get_warehouse_goods_stage_data(self.warehouse_id, self.first_stage_day,
  124. self.second_stage_day, self.third_stage_day)
  125. non_active_id_list = []
  126. for vals in data_vals_list:
  127. if vals.get('subtotal', 0) != 0:
  128. # 更新最后发货日期和最后发货数量
  129. latest_move_line = self.env['wh.move.line'].search([
  130. ('state', '=', 'done'),
  131. ('goods_id', '=', vals.get('goods_id')),
  132. ('attribute_id', '=', vals.get('attribute_id')),
  133. ('warehouse_id.type', '=', 'stock'),
  134. ('warehouse_dest_id.type', '=', 'customer')], order='write_date DESC', limit=1)
  135. if latest_move_line:
  136. vals['latest_move_date'] = latest_move_line.write_date
  137. vals['latest_move_qty'] = latest_move_line.goods_qty
  138. active_row = self.env['non.active.report'].create(vals)
  139. non_active_id_list.append(active_row.id)
  140. view = self.env.ref('warehouse.non_active_report_list')
  141. return {
  142. 'name': '库龄报表',
  143. 'view_mode': 'list',
  144. 'views': [(view.id, 'list')],
  145. 'res_model': 'non.active.report',
  146. 'type': 'ir.actions.act_window',
  147. 'target': 'main',
  148. 'domain': [('id', 'in', non_active_id_list)],
  149. 'limit': 65535,
  150. 'context': {'first_stage_day': self.first_stage_day,
  151. 'second_stage_day': self.second_stage_day, 'third_stage_day': self.third_stage_day}
  152. }
上海开阖软件有限公司 沪ICP备12045867号-1