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.

200 lines
8.5 KiB

  1. # Copyright 2019 Coop IT Easy SCRL fs
  2. # Houssine BAKKALI <houssine@coopiteasy.be>
  3. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  4. import logging
  5. from odoo import api, fields, models, _
  6. _logger = logging.getLogger(__name__)
  7. class LoanIssue(models.Model):
  8. _name = 'loan.issue'
  9. _description = 'Loan Issue'
  10. @api.multi
  11. def _compute_subscribed_amount(self):
  12. for issue in self:
  13. susbscribed_amount = 0.0
  14. for line in issue.loan_issue_lines.filtered(
  15. lambda record: record.state != 'cancelled'):
  16. susbscribed_amount += line.amount
  17. issue.subscribed_amount = susbscribed_amount
  18. name = fields.Char(string="Name",
  19. translate=True)
  20. default_issue = fields.Boolean(string="Default issue")
  21. subscription_start_date = fields.Date(string="Start date subscription period")
  22. subscription_end_date = fields.Date(string="End date subscription period")
  23. user_id = fields.Many2one('res.users',
  24. string="Responsible")
  25. loan_start_date = fields.Date(string="Loan start date")
  26. term_date = fields.Date(string="Term date")
  27. loan_term = fields.Float(string="Duration of the loan in month")
  28. rate = fields.Float(string="Interest rate")
  29. face_value = fields.Monetary(string="Facial value",
  30. currency_field='company_currency_id',
  31. required=True)
  32. minimum_amount = fields.Monetary(string="Minimum amount of issue",
  33. currency_field='company_currency_id')
  34. maximum_amount = fields.Monetary(string="Maximum amount of issue",
  35. currency_field='company_currency_id')
  36. min_amount_company = fields.Monetary(string="Minimum amount for a company",
  37. currency_field='company_currency_id')
  38. max_amount_company = fields.Monetary(string="Maximum amount for a company",
  39. currency_field='company_currency_id')
  40. min_amount_person = fields.Monetary(string="Minimum amount for a person",
  41. currency_field='company_currency_id')
  42. max_amount_person = fields.Monetary(string="Maximum amount for a person",
  43. currency_field='company_currency_id')
  44. subscribed_amount = fields.Monetary(string="Subscribed amount",
  45. compute="_compute_subscribed_amount",
  46. currency_field='company_currency_id')
  47. interest_payment = fields.Selection([('end', 'End'),
  48. ('yearly', 'Yearly')],
  49. string="Interest payment")
  50. interest_payment_info = fields.Char(string="Yearly payment on")
  51. loan_issue_lines = fields.One2many('loan.issue.line',
  52. 'loan_issue_id',
  53. string="Loan issue lines")
  54. state = fields.Selection([('draft', 'Draft'),
  55. ('confirmed', 'Confirmed'),
  56. ('cancelled', 'Cancelled'),
  57. ('ongoing', 'Ongoing'),
  58. ('closed', 'Closed')],
  59. string="State",
  60. default='draft')
  61. company_currency_id = fields.Many2one('res.currency',
  62. related='company_id.currency_id',
  63. string="Company Currency",
  64. readonly=True)
  65. company_id = fields.Many2one('res.company',
  66. string='Company',
  67. required=True,
  68. readonly=True,
  69. default=lambda self: self.env['res.company']._company_default_get()) # noqa
  70. by_company = fields.Boolean(string="By company")
  71. by_individual = fields.Boolean(string='By individuals')
  72. display_on_website = fields.Boolean(sting='Display on website')
  73. taxes_rate = fields.Float(string="Taxes on interest",
  74. required=True)
  75. @api.multi
  76. def get_max_amount(self, partner):
  77. """
  78. Return the maximum amount that partner can buy.
  79. A negative value means that there is no maximum.
  80. """
  81. self.ensure_one()
  82. lines = self.loan_issue_lines.filtered(
  83. lambda r: r.partner_id == partner and r.state != 'cancelled')
  84. already_subscribed = sum(line.amount for line in lines)
  85. max_amount = -1 # No max amount
  86. if partner.is_company and self.max_amount_company > 0:
  87. max_amount = max(0, self.max_amount_company - already_subscribed)
  88. if not partner.is_company and self.max_amount_person > 0:
  89. max_amount = max(0, self.max_amount_person - already_subscribed)
  90. return max_amount
  91. @api.multi
  92. def get_min_amount(self, partner):
  93. """
  94. Return the minimum amount that a partner must buy.
  95. A zero value means that there is no minimum amount.
  96. """
  97. self.ensure_one()
  98. lines = self.loan_issue_lines.filtered(
  99. lambda r: r.partner_id == partner and r.state != 'cancelled')
  100. amount_subscribed = sum(line.amount for line in lines)
  101. if partner.is_company:
  102. min_amount = self.min_amount_company - amount_subscribed
  103. else:
  104. min_amount = self.min_amount_person - amount_subscribed
  105. return max(0, min_amount)
  106. @api.multi
  107. def get_web_issues(self, is_company):
  108. bond_issues = self.search([
  109. ('display_on_website', '=', True),
  110. ('state', '=', 'ongoing')
  111. ])
  112. if is_company is True:
  113. return bond_issues.filtered('by_company')
  114. else:
  115. return bond_issues.filtered('by_company')
  116. @api.multi
  117. def action_confirm(self):
  118. self.ensure_one()
  119. self.write({'state': 'confirmed'})
  120. @api.multi
  121. def action_open(self):
  122. self.ensure_one()
  123. self.write({'state': 'ongoing'})
  124. @api.multi
  125. def action_draft(self):
  126. self.ensure_one()
  127. self.write({'state': 'draft'})
  128. @api.multi
  129. def action_cancel(self):
  130. self.ensure_one()
  131. self.write({'state': 'cancelled'})
  132. @api.multi
  133. def action_close(self):
  134. self.ensure_one()
  135. self.write({'state': 'closed'})
  136. def get_interest_vals(self, line, vals):
  137. interest_obj = self.env['loan.interest.line']
  138. accrued_amount = line.amount
  139. accrued_interest = 0
  140. accrued_net_interest = 0
  141. accrued_taxes = 0
  142. for year in range(1, int(self.loan_term) + 1):
  143. interest = accrued_amount * (line.loan_issue_id.rate / 100)
  144. accrued_amount += interest
  145. taxes_amount = interest * (self.taxes_rate / 100)
  146. net_interest = interest - taxes_amount
  147. accrued_interest += interest
  148. accrued_net_interest += net_interest
  149. accrued_taxes += taxes_amount
  150. vals['interest'] = interest
  151. vals['net_interest'] = net_interest
  152. vals['taxes_amount'] = taxes_amount
  153. vals['accrued_amount'] = accrued_amount
  154. vals['accrued_interest'] = accrued_interest
  155. vals['accrued_net_interest'] = accrued_net_interest
  156. vals['accrued_taxes'] = accrued_taxes
  157. vals['name'] = year
  158. interest_obj.create(vals)
  159. @api.multi
  160. def compute_loan_interest(self):
  161. self.ensure_one()
  162. if self.interest_payment == 'end':
  163. due_date = self.term_date
  164. else:
  165. raise NotImplementedError(_("Interest payment by year hasn't been "
  166. "implemented yet"))
  167. for line in self.loan_issue_lines:
  168. # TODO remove this line
  169. line.interest_lines.unlink()
  170. # Please Do not Forget
  171. vals = {
  172. 'issue_line': line.id,
  173. 'due_date': due_date,
  174. 'taxes_rate': self.taxes_rate
  175. }
  176. self.get_interest_vals(line, vals)
  177. rounded_term = int(self.loan_term)
  178. if self.loan_term - rounded_term > 0:
  179. # TODO Handle this case
  180. raise NotImplementedError(_("Calculation on non entire year "
  181. "hasn't been implemented yet"))