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.

144 lines
6.1KB

  1. from datetime import date
  2. from odoo import models, fields, api
  3. from odoo.exceptions import UserError
  4. class SellReceiptWizard(models.TransientModel):
  5. _name = 'sell.receipt.wizard'
  6. _description = '销售收款一览表向导'
  7. @api.model
  8. def _default_date_start(self):
  9. return self.env.user.company_id.start_date
  10. @api.model
  11. def _default_date_end(self):
  12. return date.today()
  13. date_start = fields.Date('开始日期', default=_default_date_start,
  14. help='报表汇总的开始日期,默认为公司启用日期')
  15. date_end = fields.Date('结束日期', default=_default_date_end,
  16. help='报表汇总的结束日期,默认为当前日期')
  17. c_category_id = fields.Many2one('core.category', '客户类别',
  18. domain=[('type', '=', 'customer')],
  19. context={'type': 'customer'},
  20. help='只统计选定的客户类别')
  21. partner_id = fields.Many2one('partner', '客户',
  22. help='只统计选定的客户')
  23. user_id = fields.Many2one('res.users', '销售员',
  24. help='只统计选定的销售员')
  25. warehouse_id = fields.Many2one('warehouse', '仓库',
  26. help='只统计选定的仓库')
  27. company_id = fields.Many2one(
  28. 'res.company',
  29. string='公司',
  30. change_default=True,
  31. default=lambda self: self.env.company)
  32. def _get_domain(self):
  33. '''返回wizard界面上条件'''
  34. cond = [('date', '>=', self.date_start),
  35. ('date', '<=', self.date_end),
  36. ('state', '=', 'done')]
  37. if self.c_category_id:
  38. cond.append(
  39. ('partner_id.c_category_id', '=', self.c_category_id.id)
  40. )
  41. if self.partner_id:
  42. cond.append(('partner_id', '=', self.partner_id.id))
  43. if self.user_id:
  44. cond.append(('user_id', '=', self.user_id.id))
  45. if self.warehouse_id:
  46. cond += ['|', ('warehouse_id', '=', self.warehouse_id.id),
  47. ('warehouse_dest_id', '=', self.warehouse_id.id)]
  48. return cond
  49. def _compute_receipt(self, delivery):
  50. '''计算该发货单的已收款'''
  51. invoices = self.env['money.invoice'].search([
  52. ('name', '=', delivery.name),
  53. ('state', '=', 'done')])
  54. receipt = sum([invoice.reconciled for invoice in invoices])
  55. return receipt
  56. def _prepare_sell_receipt(self, delivery):
  57. '''对于传入的发货单/退货单,为创建销售收款一览表准备数据'''
  58. self.ensure_one()
  59. factor = delivery.is_return and -1 or 1 # 如果是退货则金额均取反
  60. sell_amount = factor * (delivery.discount_amount + delivery.amount)
  61. discount_amount = factor * delivery.discount_amount
  62. amount = factor * delivery.amount
  63. partner_cost = factor * delivery.partner_cost
  64. order_type = not delivery.is_return and '普通销售' or '销售退回'
  65. warehouse = not delivery.is_return and delivery.warehouse_id or delivery.warehouse_dest_id
  66. # 计算该发货单的已收款
  67. receipt = self._compute_receipt(delivery)
  68. # 计算回款率
  69. receipt_rate = (amount + partner_cost) != 0 and (receipt /
  70. (amount + partner_cost)) * 100 or 0
  71. return {
  72. 'c_category_id': delivery.partner_id.c_category_id.id,
  73. 'partner_id': delivery.partner_id.id,
  74. 'user_id': delivery.user_id.id,
  75. 'type': order_type,
  76. 'date': delivery.date,
  77. 'order_name': delivery.name,
  78. 'warehouse_id': warehouse.id,
  79. 'sell_amount': sell_amount,
  80. 'discount_amount': discount_amount,
  81. 'amount': amount,
  82. 'partner_cost': partner_cost,
  83. 'receipt': receipt,
  84. 'balance': amount + partner_cost - receipt,
  85. 'receipt_rate': receipt_rate,
  86. 'note': delivery.note,
  87. }
  88. def compute_partner_receipt(self, partner):
  89. """该客户所有收款单未核销金额合计数"""
  90. orders = self.env['money.order'].search([
  91. ('state', '=', 'done'),
  92. ('partner_id', '=', partner.id)])
  93. sum_amount = sum(order.to_reconcile for order in orders)
  94. return sum_amount
  95. def button_ok(self):
  96. self.ensure_one()
  97. res = []
  98. dict_part = {}
  99. if self.date_end < self.date_start:
  100. raise UserError('开始日期不能大于结束日期!\n 所选的开始日期:%s 结束日期:%s' %
  101. (self.date_start, self.date_end))
  102. delivery_obj = self.env['sell.delivery']
  103. for delivery in delivery_obj.search(self._get_domain(), order='partner_id'):
  104. if delivery.partner_id not in dict_part:
  105. dict_part[delivery.partner_id] = delivery
  106. else:
  107. dict_part[delivery.partner_id] += delivery
  108. for partner, deliverys in dict_part.items():
  109. for delivery in deliverys:
  110. # 用查找到的发货单信息来创建一览表
  111. line = self.env['sell.receipt'].create(
  112. self._prepare_sell_receipt(delivery))
  113. res.append(line.id)
  114. # 增加一行,编号是未核销预收款,已收款是该客户所有收款单未核销金额合计数,应收款余额为负的预收款
  115. summary_line = self.env['sell.receipt'].create({
  116. 'partner_id': partner.id,
  117. 'order_name': '未核销预收款',
  118. 'receipt': self.compute_partner_receipt(partner),
  119. 'balance': -self.compute_partner_receipt(partner),
  120. })
  121. res.append(summary_line.id)
  122. return {
  123. 'name': '销售收款一览表',
  124. 'view_mode': 'list',
  125. 'res_model': 'sell.receipt',
  126. 'type': 'ir.actions.act_window',
  127. 'target': 'main',
  128. 'domain': [('id', 'in', res)],
  129. 'limit': 65535,
  130. }
上海开阖软件有限公司 沪ICP备12045867号-1