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.

128 lines
5.6 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2016 Carlos Dauden <carlos.dauden@tecnativa.com>
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  4. from datetime import datetime
  5. from dateutil.relativedelta import relativedelta
  6. from openerp import api, fields, models
  7. class ResPartner(models.Model):
  8. _inherit = 'res.partner'
  9. risk_invoice_draft_include = fields.Boolean(
  10. string='Include Draft Invoices', help='Full risk computation')
  11. risk_invoice_draft_limit = fields.Monetary(
  12. string='Limit In Draft Invoices', help='Set 0 if it is not locked')
  13. risk_invoice_draft = fields.Monetary(
  14. compute='_compute_risk_invoice', store=True,
  15. string='Total Draft Invoices',
  16. help='Total amount of invoices in Draft or Pro-forma state')
  17. risk_invoice_open_include = fields.Boolean(
  18. string='Include Open Invoices', help='Full risk computation')
  19. risk_invoice_open_limit = fields.Monetary(
  20. string='Limit In Open Invoices', help='Set 0 if it is not locked')
  21. risk_invoice_open = fields.Monetary(
  22. compute='_compute_risk_invoice', store=True,
  23. string='Total Open Invoices',
  24. help='Residual amount of invoices in Open state and the date due is '
  25. 'not exceeded, considering Due Margin set in account '
  26. 'settings')
  27. risk_invoice_unpaid_include = fields.Boolean(
  28. string='Include Due Invoices', help='Full risk computation')
  29. risk_invoice_unpaid_limit = fields.Monetary(
  30. string='Limit In Due Invoices', help='Set 0 if it is not locked')
  31. risk_invoice_unpaid = fields.Monetary(
  32. compute='_compute_risk_invoice', store=True,
  33. string='Total Due Invoices',
  34. help='Residual amount of invoices in Open state and the date due is '
  35. 'exceeded, considering Due Margin set in account settings')
  36. risk_account_amount_include = fields.Boolean(
  37. string='Include Other Account Amount', help='Full risk computation')
  38. risk_account_amount_limit = fields.Monetary(
  39. string='Limit Other Account Amount', help='Set 0 if it is not locked')
  40. risk_account_amount = fields.Monetary(
  41. compute='_compute_risk_account_amount',
  42. string='Other Account Amount',
  43. help='Difference between accounting credit and rest of totals')
  44. risk_total = fields.Monetary(
  45. compute='_compute_risk_exception',
  46. string='Total Risk', help='Sum of total risk included')
  47. risk_exception = fields.Boolean(
  48. compute='_compute_risk_exception',
  49. string='Risk Exception',
  50. help='It Indicate if partner risk exceeded')
  51. @api.multi
  52. @api.depends('invoice_ids', 'invoice_ids.state',
  53. 'invoice_ids.amount_total', 'invoice_ids.residual',
  54. 'invoice_ids.company_id.invoice_due_margin')
  55. def _compute_risk_invoice(self):
  56. max_date = self._max_risk_date_due()
  57. for partner in self:
  58. invoices_out = partner.invoice_ids.filtered(
  59. lambda x: x.type == 'out_invoice')
  60. invoices = invoices_out.filtered(
  61. lambda x: x.state in ['draft', 'proforma', 'proforma2'])
  62. partner.risk_invoice_draft = sum(invoices.mapped('amount_total'))
  63. invoices = invoices_out.filtered(
  64. lambda x: x.state == 'open' and x.date_due >= max_date)
  65. partner.risk_invoice_open = sum(invoices.mapped('residual'))
  66. invoices = invoices_out.filtered(
  67. lambda x: x.state == 'open' and x.date_due < max_date)
  68. partner.risk_invoice_unpaid = sum(invoices.mapped('residual'))
  69. @api.multi
  70. @api.depends('credit', 'risk_invoice_open', 'risk_invoice_unpaid')
  71. def _compute_risk_account_amount(self):
  72. for partner in self:
  73. partner.risk_account_amount = (
  74. partner.credit - partner.risk_invoice_open -
  75. partner.risk_invoice_unpaid)
  76. @api.multi
  77. @api.depends(lambda x: x._get_depends_compute_risk_exception())
  78. def _compute_risk_exception(self):
  79. risk_field_list = self._risk_field_list()
  80. for partner in self:
  81. amount = 0.0
  82. for risk_field in risk_field_list:
  83. field_value = getattr(partner, risk_field[0], 0.0)
  84. max_value = getattr(partner, risk_field[1], 0.0)
  85. if max_value and field_value > max_value:
  86. partner.risk_exception = True
  87. if getattr(partner, risk_field[2], False):
  88. amount += field_value
  89. partner.risk_total = amount
  90. if amount > partner.credit_limit:
  91. partner.risk_exception = True
  92. @api.model
  93. def _max_risk_date_due(self):
  94. return fields.Date.to_string(datetime.today().date() - relativedelta(
  95. days=self.env.user.company_id.invoice_due_margin))
  96. @api.model
  97. def _risk_field_list(self):
  98. return [
  99. ('risk_invoice_draft', 'risk_invoice_draft_limit',
  100. 'risk_invoice_draft_include'),
  101. ('risk_invoice_open', 'risk_invoice_open_limit',
  102. 'risk_invoice_open_include'),
  103. ('risk_invoice_unpaid', 'risk_invoice_unpaid_limit',
  104. 'risk_invoice_unpaid_include'),
  105. ('risk_account_amount', 'risk_account_amount_limit',
  106. 'risk_account_amount_include'),
  107. ]
  108. @api.model
  109. def _get_depends_compute_risk_exception(self):
  110. # TODO: Improve code without lose performance
  111. tuple_list = self._risk_field_list()
  112. res = [x[0] for x in tuple_list]
  113. res.extend([x[1] for x in tuple_list])
  114. res.extend([x[2] for x in tuple_list])
  115. res.append('credit_limit')
  116. return res