From 3b92b3dca6703a141ce28e630efe343c4b8fe64f Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Wed, 26 Jun 2019 10:23:23 +0200 Subject: [PATCH] [IMP] account_loan: Add fixed-annuity-begin --- account_loan/__manifest__.py | 4 +-- account_loan/model/account_loan.py | 9 +++++ account_loan/model/account_loan_line.py | 32 +++++++++++++++--- account_loan/tests/test_loan.py | 44 +++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/account_loan/__manifest__.py b/account_loan/__manifest__.py index f14043e4a..028568880 100644 --- a/account_loan/__manifest__.py +++ b/account_loan/__manifest__.py @@ -1,8 +1,8 @@ # Copyright 2018 Creu Blanca # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - "name": "Account Loan", - "version": "12.0.1.0.0", + "name": "Account Loan management", + "version": "12.0.1.1.0", "author": "Creu Blanca,Odoo Community Association (OCA)", "website": "http://github.com/OCA/account-financial-tools", "license": "AGPL-3", diff --git a/account_loan/model/account_loan.py b/account_loan/model/account_loan.py index 9a447af25..73ab196a1 100644 --- a/account_loan/model/account_loan.py +++ b/account_loan/model/account_loan.py @@ -106,6 +106,7 @@ class AccountLoan(models.Model): loan_type = fields.Selection( [ ('fixed-annuity', 'Fixed Annuity'), + ('fixed-annuity-begin', 'Fixed Annuity Begin'), ('fixed-principal', 'Fixed Principal'), ('interest', 'Only interest'), ], @@ -281,6 +282,14 @@ class AccountLoan(models.Model): record.fixed_loan_amount, -record.residual_amount )) + elif record.loan_type == 'fixed-annuity-begin': + record.fixed_amount = - record.currency_id.round(numpy.pmt( + record.loan_rate() / 100, + record.fixed_periods, + record.fixed_loan_amount, + -record.residual_amount, + when='begin' + )) elif record.loan_type == 'fixed-principal': record.fixed_amount = record.currency_id.round( (record.fixed_loan_amount - record.residual_amount) / diff --git a/account_loan/model/account_loan_line.py b/account_loan/model/account_loan_line.py index 3b8fbb047..4bad7b384 100644 --- a/account_loan/model/account_loan_line.py +++ b/account_loan/model/account_loan_line.py @@ -166,6 +166,19 @@ class AccountLoanLine(models.Model): self.pending_principal_amount, -self.loan_id.residual_amount )) + if ( + self.loan_type == 'fixed-annuity-begin' and + self.loan_id.round_on_end + ): + return self.loan_id.fixed_amount + if self.loan_type == 'fixed-annuity-begin': + return self.currency_id.round(- numpy.pmt( + self.loan_id.loan_rate() / 100, + self.loan_id.periods - self.sequence + 1, + self.pending_principal_amount, + -self.loan_id.residual_amount, + when='begin' + )) def check_amount(self): """Recompute amounts if the annuity has not been processed""" @@ -177,7 +190,7 @@ class AccountLoanLine(models.Model): if ( self.sequence == self.loan_id.periods and self.loan_id.round_on_end and - self.loan_type == 'fixed-annuity' + self.loan_type in ['fixed-annuity', 'fixed-annuity-begin'] ): self.interests_amount = self.currency_id.round( self.loan_id.fixed_amount - self.pending_principal_amount + @@ -186,13 +199,24 @@ class AccountLoanLine(models.Model): self.payment_amount = self.currency_id.round(self.compute_amount()) elif not self.loan_id.round_on_end: self.interests_amount = self.currency_id.round( - self.pending_principal_amount * self.loan_id.loan_rate() / 100) + self.compute_interest()) self.payment_amount = self.currency_id.round(self.compute_amount()) else: - self.interests_amount = ( - self.pending_principal_amount * self.loan_id.loan_rate() / 100) + self.interests_amount = self.compute_interest() self.payment_amount = self.compute_amount() + def compute_interest(self): + if self.loan_type == 'fixed-annuity-begin': + return -numpy.ipmt( + self.loan_id.loan_rate() / 100, + 2, + self.loan_id.periods - self.sequence + 1, + self.pending_principal_amount, + -self.loan_id.residual_amount, + when='begin' + ) + return self.pending_principal_amount * self.loan_id.loan_rate() / 100 + @api.multi def check_move_amount(self): """ diff --git a/account_loan/tests/test_loan.py b/account_loan/tests/test_loan.py index e05e69a4c..b74e3d86c 100644 --- a/account_loan/tests/test_loan.py +++ b/account_loan/tests/test_loan.py @@ -164,6 +164,50 @@ class TestLoan(TransactionCase): 'date': line.date, }).run() + def test_fixed_annuity_begin_loan(self): + amount = 10000 + periods = 24 + loan = self.create_loan('fixed-annuity-begin', amount, 1, periods) + self.assertTrue(loan.line_ids) + self.assertEqual(len(loan.line_ids), periods) + line = loan.line_ids.filtered(lambda r: r.sequence == 1) + self.assertAlmostEqual( + - numpy.pmt(1 / 100 / 12, 24, 10000, when='begin'), + line.payment_amount, 2) + self.assertEqual(line.long_term_principal_amount, 0) + loan.long_term_loan_account_id = self.lt_loan_account + loan.compute_lines() + line = loan.line_ids.filtered(lambda r: r.sequence == 1) + self.assertGreater(line.long_term_principal_amount, 0) + self.post(loan) + self.assertTrue(loan.start_date) + line = loan.line_ids.filtered(lambda r: r.sequence == 1) + self.assertTrue(line) + self.assertFalse(line.move_ids) + self.assertFalse(line.invoice_ids) + wzd = self.env['account.loan.generate.wizard'].create({}) + action = wzd.run() + self.assertTrue(action) + self.assertFalse(wzd.run()) + self.assertTrue(line.move_ids) + self.assertIn(line.move_ids.id, action['domain'][0][2]) + line.move_ids.post() + loan.rate = 2 + loan.compute_lines() + line = loan.line_ids.filtered(lambda r: r.sequence == 1) + self.assertAlmostEqual( + - numpy.pmt(1 / 100 / 12, periods, amount, when='begin'), + line.payment_amount, 2) + line = loan.line_ids.filtered(lambda r: r.sequence == 2) + self.assertAlmostEqual( + - numpy.pmt(2 / 100 / 12, periods - 1, + line.pending_principal_amount, when='begin'), + line.payment_amount, 2 + ) + line = loan.line_ids.filtered(lambda r: r.sequence == 3) + with self.assertRaises(UserError): + line.view_process_values() + def test_fixed_annuity_loan(self): amount = 10000 periods = 24