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.

233 lines
7.6 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 calendar
  5. from datetime import date
  6. from dateutil.relativedelta import relativedelta
  7. from odoo import api, fields, models
  8. class LoanIssueLine(models.Model):
  9. _name = "loan.issue.line"
  10. _description = "Loan Issue Line"
  11. _order = "date desc, id"
  12. @api.multi
  13. @api.depends("quantity", "face_value")
  14. def _compute_amount(self):
  15. for line in self:
  16. line.amount = line.face_value * line.quantity
  17. name = fields.Char(string="Reference")
  18. loan_issue_id = fields.Many2one(
  19. "loan.issue", string="Loan issue", required=True
  20. )
  21. interest_lines = fields.One2many(
  22. "loan.interest.line", "issue_line", string="Interest lines"
  23. )
  24. quantity = fields.Integer(string="quantity", required=True)
  25. face_value = fields.Monetary(
  26. related="loan_issue_id.face_value",
  27. currency_field="company_currency_id",
  28. store=True,
  29. readonly=True,
  30. )
  31. partner_id = fields.Many2one(
  32. "res.partner", string="Subscriber", required=True
  33. )
  34. date = fields.Date(
  35. string="Subscription date",
  36. default=lambda self: date.strftime(date.today(), "%Y-%m-%d"),
  37. required=True,
  38. )
  39. payment_date = fields.Date(
  40. string="Payment date")
  41. amount = fields.Monetary(
  42. string="Subscribed amount",
  43. currency_field="company_currency_id",
  44. compute="_compute_amount",
  45. store=True,
  46. )
  47. state = fields.Selection(
  48. [
  49. ("draft", "Draft"),
  50. ("subscribed", "Subscribed"),
  51. ("waiting", "Waiting payment"),
  52. ("paid", "paid"),
  53. ("cancelled", "Cancelled"),
  54. ("ended", "Ended"),
  55. ],
  56. string="State",
  57. required=True,
  58. default="draft",
  59. )
  60. company_currency_id = fields.Many2one(
  61. "res.currency",
  62. related="company_id.currency_id",
  63. string="Company Currency",
  64. readonly=True,
  65. )
  66. company_id = fields.Many2one(
  67. "res.company",
  68. related="loan_issue_id.company_id",
  69. string="Company",
  70. readonly=True,
  71. )
  72. def get_loan_sub_mail_template(self):
  73. return self.env.ref(
  74. "easy_my_coop_loan.loan_subscription_confirmation", False
  75. )
  76. def get_loan_pay_req_mail_template(self):
  77. return self.env.ref(
  78. "easy_my_coop_loan.loan_issue_payment_request", False
  79. )
  80. @api.model
  81. def create(self, vals):
  82. line = super(LoanIssueLine, self).create(vals)
  83. confirmation_mail_template = line.get_loan_sub_mail_template()
  84. confirmation_mail_template.send_mail(line.id)
  85. return line
  86. @api.multi
  87. def action_draft(self):
  88. for line in self:
  89. line.write({"state": "draft"})
  90. @api.multi
  91. def action_validate(self):
  92. for line in self:
  93. line.write({"state": "subscribed"})
  94. @api.multi
  95. def action_request_payment(self):
  96. pay_req_mail_template = self.get_loan_pay_req_mail_template()
  97. for line in self:
  98. pay_req_mail_template.send_mail(line.id)
  99. line.write({"state": "waiting"})
  100. @api.multi
  101. def action_cancel(self):
  102. for line in self:
  103. line.write({"state": "cancelled"})
  104. @api.multi
  105. def get_confirm_paid_email_template(self):
  106. self.ensure_one()
  107. return self.env.ref(
  108. "easy_my_coop_loan.email_template_loan_confirm_paid"
  109. )
  110. @api.multi
  111. def action_paid(self):
  112. for line in self:
  113. loan_email_template = self.get_confirm_paid_email_template()
  114. loan_email_template.sudo().send_mail(line.id, force_send=False)
  115. vals = {"state": "paid"}
  116. if not line.payment_date:
  117. vals["payement_date"] = fields.Date.today()
  118. line.write(vals)
  119. def get_number_of_days(self, year):
  120. if calendar.isleap(year):
  121. return 366
  122. else:
  123. return 365
  124. @api.multi
  125. def action_compute_interest(self):
  126. for line in self:
  127. loan_issue = line.loan_issue_id
  128. vals = {
  129. "issue_line": line.id,
  130. "taxes_rate": loan_issue.taxes_rate,
  131. }
  132. list_vals = []
  133. accrued_amount = self.amount
  134. accrued_interest = 0
  135. accrued_net_interest = 0
  136. accrued_taxes = 0
  137. taxes_amount = 0
  138. diff_days = 0
  139. # TODO remove this line
  140. line.interest_lines.unlink()
  141. # Please Do not Forget
  142. loan_term = int(loan_issue.loan_term / 12)
  143. # if payment_date is first day of the month
  144. # we take the current month
  145. if line.payment_date.day == 1:
  146. start_date = line.payment_date
  147. else:
  148. start_date = line.payment_date + relativedelta(months=+1,
  149. day=1)
  150. # we calculate the number of day between payment date
  151. # and the end of the month of the payment
  152. diff_days = ((start_date - relativedelta(days=1)) -
  153. line.payment_date).days
  154. rate = loan_issue.rate / 100
  155. # take leap year into account
  156. days = self.get_number_of_days(line.payment_date.year)
  157. interim_amount = line.amount * rate * (diff_days / days)
  158. due_date = start_date + relativedelta(years=+loan_term)
  159. for year in range(1, loan_term + 1):
  160. interest = accrued_amount * rate
  161. due_amount = 0
  162. if loan_issue.capital_payment == "end":
  163. if year == loan_term:
  164. due_amount = line.amount
  165. else:
  166. due_amount = line.amount * (loan_term / 100)
  167. accrued_amount -= due_amount
  168. if loan_issue.interest_payment == "end":
  169. accrued_interest += interest
  170. accrued_amount += interest
  171. net_interest = 0
  172. if year == loan_term:
  173. taxes_amount = (accrued_interest *
  174. (loan_issue.taxes_rate / 100)
  175. )
  176. net_interest = accrued_interest - taxes_amount
  177. due_amount += net_interest
  178. else:
  179. due_date = start_date + relativedelta(years=+year)
  180. taxes_amount = interest * (loan_issue.taxes_rate / 100)
  181. net_interest = interest - taxes_amount
  182. due_amount += net_interest
  183. accrued_interest = interest
  184. if year == 1:
  185. interest += interim_amount
  186. accrued_interest = interest
  187. accrued_net_interest += net_interest
  188. accrued_taxes += taxes_amount
  189. vals["due_date"] = due_date
  190. vals["due_amount"] = due_amount
  191. vals["interest"] = interest
  192. vals["net_interest"] = net_interest
  193. vals["taxes_amount"] = taxes_amount
  194. vals["accrued_amount"] = accrued_amount
  195. vals["accrued_interest"] = accrued_interest
  196. vals["accrued_net_interest"] = accrued_net_interest
  197. vals["accrued_taxes"] = accrued_taxes
  198. vals["name"] = year
  199. list_vals.append(vals.copy())
  200. self.env["loan.interest.line"].create(list_vals)