diff --git a/account_loan/__manifest__.py b/account_loan/__manifest__.py index 8ad68efe..b2fa61f0 100644 --- a/account_loan/__manifest__.py +++ b/account_loan/__manifest__.py @@ -9,6 +9,7 @@ "category": "Accounting", "depends": ["account"], "data": [ + "wizards/account_loan_increase_amount.xml", "data/ir_sequence_data.xml", "security/ir.model.access.csv", "security/account_loan_security.xml", diff --git a/account_loan/models/account_loan_line.py b/account_loan/models/account_loan_line.py index 47313f62..f5457714 100644 --- a/account_loan/models/account_loan_line.py +++ b/account_loan/models/account_loan_line.py @@ -238,34 +238,38 @@ class AccountLoanLine(models.Model): + self.interests_amount ) - def _move_vals(self): + def _move_vals(self, journal=False, account=False): return { "loan_line_id": self.id, "loan_id": self.loan_id.id, "date": self.date, "ref": self.name, - "journal_id": self.loan_id.journal_id.id, - "line_ids": [Command.create(vals) for vals in self._move_line_vals()], + "journal_id": (journal and journal.id) or self.loan_id.journal_id.id, + "line_ids": [ + Command.create(vals) for vals in self._move_line_vals(account=account) + ], } - def _move_line_vals(self): + def _move_line_vals(self, account=False): vals = [] partner = self.loan_id.partner_id.with_company(self.loan_id.company_id) vals.append( { - "account_id": partner.property_account_payable_id.id, + "account_id": (account and account.id) + or partner.property_account_payable_id.id, "partner_id": partner.id, "credit": self.payment_amount, "debit": 0, } ) - vals.append( - { - "account_id": self.loan_id.interest_expenses_account_id.id, - "credit": 0, - "debit": self.interests_amount, - } - ) + if self.interests_amount: + vals.append( + { + "account_id": self.loan_id.interest_expenses_account_id.id, + "credit": 0, + "debit": self.interests_amount, + } + ) vals.append( { "account_id": self.loan_id.short_term_loan_account_id.id, @@ -326,7 +330,7 @@ class AccountLoanLine(models.Model): ) return vals - def _generate_move(self): + def _generate_move(self, journal=False, account=False): """ Computes and post the moves of loans :return: list of account.move generated @@ -338,7 +342,9 @@ class AccountLoanLine(models.Model): lambda r: r.date < record.date and not r.move_ids ): raise UserError(_("Some moves must be created first")) - move = self.env["account.move"].create(record._move_vals()) + move = self.env["account.move"].create( + record._move_vals(journal=journal, account=account) + ) move.action_post() res.append(move.id) return res @@ -372,6 +378,9 @@ class AccountLoanLine(models.Model): for line in invoice.invoice_line_ids: line.tax_ids = line._get_computed_taxes() invoice.flush_recordset() + invoice.filtered( + lambda m: m.currency_id.round(m.amount_total) < 0 + ).action_switch_invoice_into_refund_credit_note() if record.loan_id.post_invoice: invoice.action_post() if ( diff --git a/account_loan/security/ir.model.access.csv b/account_loan/security/ir.model.access.csv index 4046d304..1245d713 100644 --- a/account_loan/security/ir.model.access.csv +++ b/account_loan/security/ir.model.access.csv @@ -5,4 +5,5 @@ access_account_loan_line,account.loan.line,model_account_loan_line,account.group access_account_loan_line_manager,account.loan.line,model_account_loan_line,account.group_account_manager,1,1,1,1 access_account_loan_generate_wizard,access_account_loan_generate_wizard,model_account_loan_generate_wizard,account.group_account_manager,1,1,1,1 access_account_loan_pay_amount,access_account_loan_pay_amount,model_account_loan_pay_amount,account.group_account_manager,1,1,1,1 +access_account_loan_increase_amount,access_account_loan_increase_amount,model_account_loan_increase_amount,account.group_account_manager,1,1,1,1 access_account_loan_post,access_account_loan_post,model_account_loan_post,account.group_account_manager,1,1,1,1 diff --git a/account_loan/tests/test_loan.py b/account_loan/tests/test_loan.py index d4f453ff..45e183d4 100644 --- a/account_loan/tests/test_loan.py +++ b/account_loan/tests/test_loan.py @@ -103,6 +103,52 @@ class TestLoan(TransactionCase): self.assertEqual(line_1.principal_amount, 0) self.assertEqual(line_end.principal_amount, 500000) + def test_increase_amount_validation(self): + amount = 10000 + periods = 24 + loan = self.create_loan("fixed-annuity", 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_financial.pmt(1 / 100 / 12, 24, 10000), 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) + 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]) + self.assertTrue(line.move_ids) + self.assertEqual(line.move_ids.state, "posted") + with self.assertRaises(UserError): + self.env["account.loan.increase.amount"].with_context( + default_loan_id=loan.id + ).create( + { + "amount": (amount - amount / periods) / 2, + "date": line.date + relativedelta(months=-1), + } + ).run() + with self.assertRaises(UserError): + self.env["account.loan.increase.amount"].with_context( + default_loan_id=loan.id + ).create({"amount": 0, "date": line.date}).run() + with self.assertRaises(UserError): + self.env["account.loan.increase.amount"].with_context( + default_loan_id=loan.id + ).create({"amount": -100, "date": line.date}).run() + def test_pay_amount_validation(self): amount = 10000 periods = 24 @@ -132,26 +178,125 @@ class TestLoan(TransactionCase): self.assertTrue(line.move_ids) self.assertEqual(line.move_ids.state, "posted") with self.assertRaises(UserError): - self.env["account.loan.pay.amount"].create( + self.env["account.loan.pay.amount"].with_context( + default_loan_id=loan.id + ).create( { - "loan_id": loan.id, "amount": (amount - amount / periods) / 2, "fees": 100, "date": line.date + relativedelta(months=-1), } ).run() with self.assertRaises(UserError): - self.env["account.loan.pay.amount"].create( - {"loan_id": loan.id, "amount": amount, "fees": 100, "date": line.date} - ).run() + self.env["account.loan.pay.amount"].with_context( + default_loan_id=loan.id + ).create({"amount": amount, "fees": 100, "date": line.date}).run() with self.assertRaises(UserError): - self.env["account.loan.pay.amount"].create( - {"loan_id": loan.id, "amount": 0, "fees": 100, "date": line.date} - ).run() + self.env["account.loan.pay.amount"].with_context( + default_loan_id=loan.id + ).create({"amount": 0, "fees": 100, "date": line.date}).run() with self.assertRaises(UserError): - self.env["account.loan.pay.amount"].create( - {"loan_id": loan.id, "amount": -100, "fees": 100, "date": line.date} - ).run() + self.env["account.loan.pay.amount"].with_context( + default_loan_id=loan.id + ).create({"amount": -100, "fees": 100, "date": line.date}).run() + + def test_increase_amount_loan(self): + amount = 10000 + periods = 24 + loan = self.create_loan("fixed-annuity", 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_financial.pmt(1 / 100 / 12, 24, 10000), 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) + 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]) + self.assertTrue(line.move_ids) + self.assertEqual(line.move_ids.state, "posted") + pending_principal_amount = loan.pending_principal_amount + action = ( + self.env["account.loan.increase.amount"] + .with_context(default_loan_id=loan.id) + .create( + { + "amount": 1000, + "date": line.date, + } + ) + .run() + ) + new_move = self.env[action["res_model"]].search(action["domain"]) + new_move.ensure_one() + self.assertFalse(new_move.is_invoice()) + self.assertEqual(loan, new_move.loan_id) + self.assertEqual(loan.pending_principal_amount, pending_principal_amount + 1000) + + def test_increase_amount_leasing(self): + amount = 10000 + periods = 24 + loan = self.create_loan("fixed-annuity", 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_financial.pmt(1 / 100 / 12, 24, 10000), line.payment_amount, 2 + ) + self.assertEqual(line.long_term_principal_amount, 0) + loan.is_leasing = True + 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) + wzd = self.env["account.loan.generate.wizard"].create( + { + "date": fields.date.today() + relativedelta(days=1), + "loan_type": "leasing", + } + ) + 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]) + self.assertTrue(line.move_ids) + self.assertEqual(line.move_ids.state, "posted") + pending_principal_amount = loan.pending_principal_amount + action = ( + self.env["account.loan.increase.amount"] + .with_context(default_loan_id=loan.id) + .create( + { + "amount": 1000, + "date": line.date, + } + ) + .run() + ) + new_move = self.env[action["res_model"]].search(action["domain"]) + new_move.ensure_one() + self.assertFalse(new_move.is_invoice()) + self.assertEqual(loan, new_move.loan_id) + self.assertEqual(loan.pending_principal_amount, pending_principal_amount + 1000) def test_fixed_annuity_begin_loan(self): amount = 10000 diff --git a/account_loan/views/account_loan_view.xml b/account_loan/views/account_loan_view.xml index 184bed31..9aea0489 100644 --- a/account_loan/views/account_loan_view.xml +++ b/account_loan/views/account_loan_view.xml @@ -66,12 +66,29 @@ + > +
+ +