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.

218 line
7.9KB

  1. from odoo import models, fields, api
  2. from datetime import datetime, timedelta
  3. class ReportStockTransceive(models.TransientModel):
  4. _name = 'report.stock.transceive'
  5. _description = '商品收发明细表'
  6. goods = fields.Char('商品')
  7. code = fields.Char('编码')
  8. attribute = fields.Char('属性')
  9. id_lists = fields.Text('库存调拨id列表')
  10. uom = fields.Char('单位')
  11. warehouse = fields.Char('仓库')
  12. goods_qty_begain = fields.Float(
  13. '期初数量', digits='Quantity')
  14. cost_begain = fields.Float(
  15. '期初成本', digits='Amount')
  16. goods_qty_end = fields.Float(
  17. '期末数量', digits='Quantity')
  18. cost_end = fields.Float(
  19. '期末成本', digits='Amount')
  20. goods_qty_out = fields.Float(
  21. '出库数量', digits='Quantity')
  22. cost_out = fields.Float(
  23. '出库成本', digits='Amount')
  24. goods_qty_in = fields.Float(
  25. '入库数量', digits='Quantity')
  26. cost_in = fields.Float(
  27. '入库成本', digits='Amount')
  28. def select_sql(self, sql_type='out'):
  29. return '''
  30. SELECT goods.name as goods,
  31. goods.code as code,
  32. att.name as attribute,
  33. array_agg(line.id) as id_lists,
  34. uom.name as uom,
  35. wh.name as warehouse,
  36. sum(case when
  37. line.date < '{date_start}' THEN line.goods_qty ELSE 0 END)
  38. as goods_qty_begain,
  39. sum(case when
  40. line.date < '{date_start}' THEN line.cost ELSE 0 END)
  41. as cost_begain,
  42. sum(case when
  43. line.date <= '{date_end}' THEN line.goods_qty ELSE 0 END)
  44. as goods_qty_end,
  45. sum(case when
  46. line.date <= '{date_end}' THEN line.cost ELSE 0 END)
  47. as cost_end,
  48. sum(case when
  49. line.date <= '{date_end}' AND line.date >= '{date_start}'
  50. THEN
  51. line.goods_qty ELSE 0 END)
  52. as goods_qty,
  53. sum(case when
  54. line.date <= '{date_end}' AND line.date >= '{date_start}'
  55. THEN
  56. line.cost ELSE 0 END)
  57. as cost
  58. '''
  59. def from_sql(self, sql_type='out'):
  60. return '''
  61. FROM wh_move_line line
  62. LEFT JOIN goods goods ON line.goods_id = goods.id
  63. LEFT JOIN attribute att ON line.attribute_id = att.id
  64. LEFT JOIN uom uom ON line.uom_id = uom.id
  65. LEFT JOIN warehouse wh ON line.%s = wh.id
  66. ''' % (sql_type == 'out' and 'warehouse_id' or 'warehouse_dest_id')
  67. def where_sql(self, sql_type='out'):
  68. extra = ''
  69. if self.env.context.get('warehouse_id'):
  70. extra += 'AND wh.id = {warehouse_id}'
  71. if self.env.context.get('goods_id'):
  72. extra += 'AND goods.id = {goods_id}'
  73. return '''
  74. WHERE line.state = 'done'
  75. AND wh.type = 'stock'
  76. AND wh.active = true
  77. AND line.date <= '{date_end}'
  78. %s
  79. ''' % extra
  80. def group_sql(self, sql_type='out'):
  81. return '''
  82. GROUP BY goods.id, goods.code, att.name, uom.name, wh.name
  83. '''
  84. def order_sql(self, sql_type='out'):
  85. return '''
  86. ORDER BY goods.id, wh.name
  87. '''
  88. def get_record_key(self, record, sql_type='out'):
  89. return (
  90. record.get('goods'),
  91. record.get('uom'),
  92. record.get('warehouse'),
  93. record.get('attribute'),
  94. record.get('code')
  95. )
  96. def unzip_record_key(self, key):
  97. return {
  98. 'goods': key[0],
  99. 'uom': key[1],
  100. 'warehouse': key[2],
  101. 'attribute': key[3],
  102. 'code': key[4],
  103. }
  104. def get_default_value_by_record(self, record, sql_type='out'):
  105. return {
  106. 'id': record.get('id'),
  107. }
  108. def update_record_value(self, value, record, sql_type='out'):
  109. tag = sql_type == 'out' and -1 or 1
  110. value.update({
  111. 'goods_qty_begain': value.get('goods_qty_begain', 0) +
  112. (tag * record.get('goods_qty_begain', 0)),
  113. 'cost_begain': value.get('cost_begain', 0) +
  114. (tag * record.get('cost_begain', 0)),
  115. 'goods_qty_end': value.get('goods_qty_end', 0) +
  116. (tag * record.get('goods_qty_end', 0)),
  117. 'cost_end': value.get('cost_end', 0) +
  118. (tag * record.get('cost_end', 0)),
  119. 'goods_qty_out': value.get('goods_qty_out', 0) +
  120. (sql_type == 'out' and record.get('goods_qty', 0) or 0),
  121. 'cost_out': value.get('cost_out', 0) +
  122. (sql_type == 'out' and record.get('cost', 0) or 0),
  123. 'goods_qty_in': value.get('goods_qty_in', 0) +
  124. (sql_type == 'in' and record.get('goods_qty', 0) or 0),
  125. 'cost_in': value.get('cost_in', 0) +
  126. (sql_type == 'in' and record.get('cost', 0) or 0),
  127. 'id_lists': value.get('id_lists', []) + record.get('id_lists', []),
  128. })
  129. def compute_history_stock_by_collect(self, res, records, sql_type='out'):
  130. for record in records:
  131. record_key = self.get_record_key(record, sql_type=sql_type)
  132. if not res.get(record_key):
  133. res[record_key] = self.get_default_value_by_record(
  134. record, sql_type=sql_type)
  135. self.update_record_value(
  136. res[record_key], record, sql_type=sql_type)
  137. def execute_sql(self, sql_type='out', wizard_id=False):
  138. context = {
  139. 'date_start': wizard_id.date_start or '',
  140. 'date_end': wizard_id.date_end or '',
  141. 'warehouse_id': wizard_id.warehouse_id and wizard_id.warehouse_id[0].id or '',
  142. 'goods_id': wizard_id.goods_id and wizard_id.goods_id[0].id or '',
  143. }
  144. for key, value in list(context.items()):
  145. if key == "date_end":
  146. continue
  147. if key == "date_start":
  148. continue
  149. if isinstance(context[key], str):
  150. context[key] = value.encode('utf-8')
  151. self.env.context = dict(self.env.context, **context)
  152. search_sql = (self.select_sql(sql_type) + self.from_sql(sql_type) + self.where_sql(
  153. sql_type) + self.group_sql(sql_type) + self.order_sql(
  154. sql_type)).format(**context)
  155. self.env.cr.execute(search_sql)
  156. return self.env.cr.dictfetchall()
  157. def collect_data_by_sql(self, wizard_id=False):
  158. out_collection = self.execute_sql(sql_type='out', wizard_id=wizard_id)
  159. in_collection = self.execute_sql(sql_type='in', wizard_id=wizard_id)
  160. res = {}
  161. self.compute_history_stock_by_collect(res, in_collection, sql_type='in')
  162. self.compute_history_stock_by_collect(res, out_collection, sql_type='out')
  163. result = []
  164. for key, value in res.items():
  165. value.update(self.unzip_record_key(key))
  166. result.append(value)
  167. return result
  168. def find_source_move_line(self):
  169. # 查看库存调拨明细
  170. move_line_ids = []
  171. # 获得'report.stock.transceive'记录集
  172. date_start = self.env.context.get('date_start')
  173. date_end = self.env.context.get('date_end')
  174. domain_dict = [
  175. ('date', '>=', date_start),
  176. ('date', '<=', date_end),
  177. ('id', 'in', [int(mid) for mid in self.id_lists[1:-1].split(',')]),
  178. ]
  179. view = self.env.ref('warehouse.wh_move_line_list')
  180. return {
  181. 'name': ('库存调拨' + str(date_start) +
  182. '~' + str(date_end) +
  183. '~' + self.goods),
  184. 'view_mode': 'list',
  185. 'views': [(view.id, 'list')],
  186. 'res_model': 'wh.move.line',
  187. 'type': 'ir.actions.act_window',
  188. 'domain': domain_dict
  189. }
上海开阖软件有限公司 沪ICP备12045867号-1