[MIG] account_loan: Migration to 13.0
Co-authored-by: Enric Tobella <etobella@creublanca.es>
This commit is contained in:
parent
e6972252f5
commit
e56f6f9e26
@ -2,7 +2,7 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
{
|
||||
"name": "Account Loan management",
|
||||
"version": "12.0.1.1.0",
|
||||
"version": "13.0.1.1.0",
|
||||
"author": "Creu Blanca,Odoo Community Association (OCA)",
|
||||
"website": "http://github.com/OCA/account-financial-tools",
|
||||
"license": "AGPL-3",
|
||||
@ -19,5 +19,5 @@
|
||||
"views/account_move_view.xml",
|
||||
],
|
||||
"installable": True,
|
||||
"external_dependencies": {"python": ["numpy",],},
|
||||
"external_dependencies": {"python": ["numpy", "numpy-financial<=1.0.0"]},
|
||||
}
|
||||
|
16
account_loan/migrations/13.0.1.1.0/post-migration.py
Normal file
16
account_loan/migrations/13.0.1.1.0/post-migration.py
Normal file
@ -0,0 +1,16 @@
|
||||
# Copyright 2021 Creu Blanca - Alba Riera
|
||||
|
||||
from openupgradelib import openupgrade
|
||||
|
||||
|
||||
@openupgrade.migrate()
|
||||
def migrate(env, version):
|
||||
openupgrade.logged_query(
|
||||
env.cr,
|
||||
"""
|
||||
UPDATE account_move am
|
||||
SET loan_line_id = ai.loan_line_id,
|
||||
loan_id = ai.loan_id
|
||||
FROM account_invoice ai
|
||||
WHERE ai.id = am.old_invoice_id and ai.loan_id is not null""",
|
||||
)
|
@ -1,7 +1,6 @@
|
||||
# Copyright 2018 Creu Blanca
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from . import account_invoice
|
||||
from . import account_loan
|
||||
from . import account_loan_line
|
||||
from . import account_move
|
||||
|
@ -1,45 +0,0 @@
|
||||
# Copyright 2018 Creu Blanca
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = "account.invoice"
|
||||
|
||||
loan_line_id = fields.Many2one(
|
||||
"account.loan.line", readonly=True, ondelete="restrict",
|
||||
)
|
||||
loan_id = fields.Many2one(
|
||||
"account.loan", readonly=True, store=True, ondelete="restrict",
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def finalize_invoice_move_lines(self, move_lines):
|
||||
vals = super().finalize_invoice_move_lines(move_lines)
|
||||
if self.loan_line_id:
|
||||
ll = self.loan_line_id
|
||||
if ll.long_term_loan_account_id and ll.long_term_principal_amount != 0:
|
||||
vals.append(
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"account_id": ll.loan_id.short_term_loan_account_id.id,
|
||||
"credit": ll.long_term_principal_amount,
|
||||
"debit": 0,
|
||||
},
|
||||
)
|
||||
)
|
||||
vals.append(
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"account_id": ll.long_term_loan_account_id.id,
|
||||
"credit": 0,
|
||||
"debit": ll.long_term_principal_amount,
|
||||
},
|
||||
)
|
||||
)
|
||||
return vals
|
@ -11,7 +11,7 @@ from odoo import api, fields, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
try:
|
||||
import numpy
|
||||
import numpy_financial
|
||||
except (ImportError, IOError) as err:
|
||||
_logger.debug(err)
|
||||
|
||||
@ -96,7 +96,7 @@ class AccountLoan(models.Model):
|
||||
help="Real rate that will be applied on each period",
|
||||
)
|
||||
rate_type = fields.Selection(
|
||||
[("napr", "Nominal APR"), ("ear", "EAR"), ("real", "Real rate"),],
|
||||
[("napr", "Nominal APR"), ("ear", "EAR"), ("real", "Real rate")],
|
||||
required=True,
|
||||
help="Method of computation of the applied rate",
|
||||
default="napr",
|
||||
@ -253,7 +253,7 @@ class AccountLoan(models.Model):
|
||||
for record in self:
|
||||
if record.loan_type == "fixed-annuity":
|
||||
record.fixed_amount = -record.currency_id.round(
|
||||
numpy.pmt(
|
||||
numpy_financial.pmt(
|
||||
record.loan_rate() / 100,
|
||||
record.fixed_periods,
|
||||
record.fixed_loan_amount,
|
||||
@ -262,7 +262,7 @@ class AccountLoan(models.Model):
|
||||
)
|
||||
elif record.loan_type == "fixed-annuity-begin":
|
||||
record.fixed_amount = -record.currency_id.round(
|
||||
numpy.pmt(
|
||||
numpy_financial.pmt(
|
||||
record.loan_rate() / 100,
|
||||
record.fixed_periods,
|
||||
record.fixed_loan_amount,
|
||||
@ -341,7 +341,6 @@ class AccountLoan(models.Model):
|
||||
vals["name"] = self.get_default_name(vals)
|
||||
return super().create(vals)
|
||||
|
||||
@api.multi
|
||||
def post(self):
|
||||
self.ensure_one()
|
||||
if not self.start_date:
|
||||
@ -349,11 +348,9 @@ class AccountLoan(models.Model):
|
||||
self.compute_draft_lines()
|
||||
self.write({"state": "posted"})
|
||||
|
||||
@api.multi
|
||||
def close(self):
|
||||
self.write({"state": "closed"})
|
||||
|
||||
@api.multi
|
||||
def compute_lines(self):
|
||||
self.ensure_one()
|
||||
if self.state == "draft":
|
||||
@ -407,7 +404,6 @@ class AccountLoan(models.Model):
|
||||
"rate": self.rate_period,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def compute_draft_lines(self):
|
||||
self.ensure_one()
|
||||
self.fixed_periods = self.periods
|
||||
@ -431,7 +427,6 @@ class AccountLoan(models.Model):
|
||||
if self.long_term_loan_account_id:
|
||||
self.check_long_term_principal_amount()
|
||||
|
||||
@api.multi
|
||||
def view_account_moves(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref("account.action_move_line_form")
|
||||
@ -439,10 +434,9 @@ class AccountLoan(models.Model):
|
||||
result["domain"] = [("loan_id", "=", self.id)]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def view_account_invoices(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref("account.action_invoice_tree2")
|
||||
action = self.env.ref("account.action_move_out_invoice_type")
|
||||
result = action.read()[0]
|
||||
result["domain"] = [("loan_id", "=", self.id), ("type", "=", "in_invoice")]
|
||||
return result
|
||||
@ -471,6 +465,6 @@ class AccountLoan(models.Model):
|
||||
[("state", "=", "posted"), ("is_leasing", "=", True)]
|
||||
):
|
||||
res += record.line_ids.filtered(
|
||||
lambda r: r.date <= date and not r.invoice_ids
|
||||
lambda r: r.date <= date and not r.move_ids
|
||||
).generate_invoice()
|
||||
return res
|
||||
|
@ -8,7 +8,7 @@ from odoo.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
try:
|
||||
import numpy
|
||||
import numpy_financial
|
||||
except (ImportError, IOError) as err:
|
||||
_logger.error(err)
|
||||
|
||||
@ -90,7 +90,6 @@ class AccountLoanLine(models.Model):
|
||||
)
|
||||
move_ids = fields.One2many("account.move", inverse_name="loan_line_id",)
|
||||
has_moves = fields.Boolean(compute="_compute_has_moves")
|
||||
invoice_ids = fields.One2many("account.invoice", inverse_name="loan_line_id",)
|
||||
has_invoices = fields.Boolean(compute="_compute_has_invoices")
|
||||
_sql_constraints = [
|
||||
(
|
||||
@ -105,10 +104,10 @@ class AccountLoanLine(models.Model):
|
||||
for record in self:
|
||||
record.has_moves = bool(record.move_ids)
|
||||
|
||||
@api.depends("invoice_ids")
|
||||
@api.depends("move_ids")
|
||||
def _compute_has_invoices(self):
|
||||
for record in self:
|
||||
record.has_invoices = bool(record.invoice_ids)
|
||||
record.has_invoices = bool(record.move_ids)
|
||||
|
||||
@api.depends("loan_id.name", "sequence")
|
||||
def _compute_name(self):
|
||||
@ -146,7 +145,7 @@ class AccountLoanLine(models.Model):
|
||||
return self.loan_id.fixed_amount
|
||||
if self.loan_type == "fixed-annuity":
|
||||
return self.currency_id.round(
|
||||
-numpy.pmt(
|
||||
-numpy_financial.pmt(
|
||||
self.loan_id.loan_rate() / 100,
|
||||
self.loan_id.periods - self.sequence + 1,
|
||||
self.pending_principal_amount,
|
||||
@ -157,7 +156,7 @@ class AccountLoanLine(models.Model):
|
||||
return self.loan_id.fixed_amount
|
||||
if self.loan_type == "fixed-annuity-begin":
|
||||
return self.currency_id.round(
|
||||
-numpy.pmt(
|
||||
-numpy_financial.pmt(
|
||||
self.loan_id.loan_rate() / 100,
|
||||
self.loan_id.periods - self.sequence + 1,
|
||||
self.pending_principal_amount,
|
||||
@ -168,7 +167,7 @@ class AccountLoanLine(models.Model):
|
||||
|
||||
def check_amount(self):
|
||||
"""Recompute amounts if the annuity has not been processed"""
|
||||
if self.move_ids or self.invoice_ids:
|
||||
if self.move_ids:
|
||||
raise UserError(
|
||||
_("Amount cannot be recomputed if moves or invoices exists " "already")
|
||||
)
|
||||
@ -192,7 +191,7 @@ class AccountLoanLine(models.Model):
|
||||
|
||||
def compute_interest(self):
|
||||
if self.loan_type == "fixed-annuity-begin":
|
||||
return -numpy.ipmt(
|
||||
return -numpy_financial.ipmt(
|
||||
self.loan_id.loan_rate() / 100,
|
||||
2,
|
||||
self.loan_id.periods - self.sequence + 1,
|
||||
@ -202,7 +201,6 @@ class AccountLoanLine(models.Model):
|
||||
)
|
||||
return self.pending_principal_amount * self.loan_id.loan_rate() / 100
|
||||
|
||||
@api.multi
|
||||
def check_move_amount(self):
|
||||
"""
|
||||
Changes the amounts of the annuity once the move is posted
|
||||
@ -286,16 +284,12 @@ class AccountLoanLine(models.Model):
|
||||
return vals
|
||||
|
||||
def invoice_vals(self):
|
||||
partner = self.loan_id.partner_id.with_context(
|
||||
force_company=self.loan_id.company_id.id
|
||||
)
|
||||
return {
|
||||
"loan_line_id": self.id,
|
||||
"loan_id": self.loan_id.id,
|
||||
"type": "in_invoice",
|
||||
"partner_id": self.loan_id.partner_id.id,
|
||||
"date_invoice": self.date,
|
||||
"account_id": partner.property_account_payable_id.id,
|
||||
"invoice_date": self.date,
|
||||
"journal_id": self.loan_id.journal_id.id,
|
||||
"company_id": self.loan_id.company_id.id,
|
||||
"invoice_line_ids": [(0, 0, vals) for vals in self.invoice_line_vals()],
|
||||
@ -323,7 +317,6 @@ class AccountLoanLine(models.Model):
|
||||
)
|
||||
return vals
|
||||
|
||||
@api.multi
|
||||
def generate_move(self):
|
||||
"""
|
||||
Computes and post the moves of loans
|
||||
@ -341,29 +334,59 @@ class AccountLoanLine(models.Model):
|
||||
res.append(move.id)
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def generate_invoice(self):
|
||||
"""
|
||||
Computes invoices of leases
|
||||
:return: list of account.invoice generated
|
||||
:return: list of account.move generated
|
||||
"""
|
||||
res = []
|
||||
for record in self:
|
||||
if not record.invoice_ids:
|
||||
if not record.move_ids:
|
||||
if record.loan_id.line_ids.filtered(
|
||||
lambda r: r.date < record.date and not r.invoice_ids
|
||||
lambda r: r.date < record.date and not r.move_ids
|
||||
):
|
||||
raise UserError(_("Some invoices must be created first"))
|
||||
invoice = self.env["account.invoice"].create(record.invoice_vals())
|
||||
invoice = self.env["account.move"].create(record.invoice_vals())
|
||||
res.append(invoice.id)
|
||||
for line in invoice.invoice_line_ids:
|
||||
line._set_taxes()
|
||||
invoice.compute_taxes()
|
||||
line.tax_ids = line._get_computed_taxes()
|
||||
invoice.with_context(
|
||||
check_move_validity=False
|
||||
)._recompute_dynamic_lines(recompute_all_taxes=True)
|
||||
invoice._check_balanced()
|
||||
if (
|
||||
record.long_term_loan_account_id
|
||||
and record.long_term_principal_amount != 0
|
||||
):
|
||||
invoice.write({"line_ids": record._get_long_term_move_line_vals()})
|
||||
if record.loan_id.post_invoice:
|
||||
invoice.action_invoice_open()
|
||||
invoice.post()
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _get_long_term_move_line_vals(self):
|
||||
return [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"account_id": self.loan_id.short_term_loan_account_id.id,
|
||||
"credit": self.long_term_principal_amount,
|
||||
"debit": 0,
|
||||
"exclude_from_invoice_tab": True,
|
||||
},
|
||||
),
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"account_id": self.long_term_loan_account_id.id,
|
||||
"credit": 0,
|
||||
"debit": self.long_term_principal_amount,
|
||||
"exclude_from_invoice_tab": True,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
def view_account_values(self):
|
||||
"""Shows the invoice if it is a leasing or the move if it is a loan"""
|
||||
self.ensure_one()
|
||||
@ -371,7 +394,6 @@ class AccountLoanLine(models.Model):
|
||||
return self.view_account_invoices()
|
||||
return self.view_account_moves()
|
||||
|
||||
@api.multi
|
||||
def view_process_values(self):
|
||||
"""Computes the annuity and returns the result"""
|
||||
self.ensure_one()
|
||||
@ -381,7 +403,6 @@ class AccountLoanLine(models.Model):
|
||||
self.generate_move()
|
||||
return self.view_account_values()
|
||||
|
||||
@api.multi
|
||||
def view_account_moves(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref("account.action_move_line_form")
|
||||
@ -397,18 +418,17 @@ class AccountLoanLine(models.Model):
|
||||
result["res_id"] = self.move_ids.id
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def view_account_invoices(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref("account.action_invoice_tree2")
|
||||
action = self.env.ref("account.action_move_out_invoice_type")
|
||||
result = action.read()[0]
|
||||
result["context"] = {
|
||||
"default_loan_line_id": self.id,
|
||||
"default_loan_id": self.loan_id.id,
|
||||
}
|
||||
result["domain"] = [("loan_line_id", "=", self.id), ("type", "=", "in_invoice")]
|
||||
if len(self.invoice_ids) == 1:
|
||||
res = self.env.ref("account.invoice.supplier.form", False)
|
||||
if len(self.move_ids) == 1:
|
||||
res = self.env.ref("account.view_move_form", False)
|
||||
result["views"] = [(res and res.id or False, "form")]
|
||||
result["res_id"] = self.invoice_ids.id
|
||||
result["res_id"] = self.move_ids.id
|
||||
return result
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Copyright 2018 Creu Blanca
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
@ -14,11 +14,10 @@ class AccountMove(models.Model):
|
||||
"account.loan", readonly=True, store=True, ondelete="restrict",
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def post(self, invoice=False):
|
||||
res = super().post(invoice=invoice)
|
||||
def post(self):
|
||||
res = super().post()
|
||||
for record in self:
|
||||
loan_line_id = record.loan_line_id or (invoice and invoice.loan_line_id)
|
||||
loan_line_id = record.loan_line_id
|
||||
if loan_line_id:
|
||||
if not record.loan_line_id:
|
||||
record.loan_line_id = loan_line_id
|
||||
|
@ -7,15 +7,16 @@ from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import fields
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import TransactionCase
|
||||
from odoo.tests import TransactionCase, tagged
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
try:
|
||||
import numpy
|
||||
import numpy_financial
|
||||
except (ImportError, IOError) as err:
|
||||
_logger.error(err)
|
||||
|
||||
|
||||
@tagged("post_install", "-at_install")
|
||||
class TestLoan(TransactionCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
@ -108,7 +109,7 @@ class TestLoan(TransactionCase):
|
||||
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), line.payment_amount, 2
|
||||
-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
|
||||
@ -120,14 +121,14 @@ class TestLoan(TransactionCase):
|
||||
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()
|
||||
self.assertTrue(line.move_ids)
|
||||
self.assertEqual(line.move_ids.state, "posted")
|
||||
with self.assertRaises(UserError):
|
||||
self.env["account.loan.pay.amount"].create(
|
||||
{
|
||||
@ -139,15 +140,15 @@ class TestLoan(TransactionCase):
|
||||
).run()
|
||||
with self.assertRaises(UserError):
|
||||
self.env["account.loan.pay.amount"].create(
|
||||
{"loan_id": loan.id, "amount": amount, "fees": 100, "date": line.date,}
|
||||
{"loan_id": loan.id, "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,}
|
||||
{"loan_id": loan.id, "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,}
|
||||
{"loan_id": loan.id, "amount": -100, "fees": 100, "date": line.date}
|
||||
).run()
|
||||
|
||||
def test_fixed_annuity_begin_loan(self):
|
||||
@ -158,7 +159,9 @@ class TestLoan(TransactionCase):
|
||||
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
|
||||
-numpy_financial.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
|
||||
@ -170,25 +173,25 @@ class TestLoan(TransactionCase):
|
||||
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()
|
||||
self.assertTrue(line.move_ids)
|
||||
self.assertEqual(line.move_ids.state, "posted")
|
||||
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"),
|
||||
-numpy_financial.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(
|
||||
-numpy_financial.pmt(
|
||||
2 / 100 / 12, periods - 1, line.pending_principal_amount, when="begin"
|
||||
),
|
||||
line.payment_amount,
|
||||
@ -206,7 +209,7 @@ class TestLoan(TransactionCase):
|
||||
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), line.payment_amount, 2
|
||||
-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
|
||||
@ -218,23 +221,25 @@ class TestLoan(TransactionCase):
|
||||
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()
|
||||
self.assertTrue(line.move_ids)
|
||||
self.assertEqual(line.move_ids.state, "posted")
|
||||
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), line.payment_amount, 2
|
||||
-numpy_financial.pmt(1 / 100 / 12, periods, amount), 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),
|
||||
-numpy_financial.pmt(
|
||||
2 / 100 / 12, periods - 1, line.pending_principal_amount
|
||||
),
|
||||
line.payment_amount,
|
||||
2,
|
||||
)
|
||||
@ -242,7 +247,7 @@ class TestLoan(TransactionCase):
|
||||
with self.assertRaises(UserError):
|
||||
line.view_process_values()
|
||||
|
||||
def test_fixed_principal_loan(self):
|
||||
def test_fixed_principal_loan_leasing(self):
|
||||
amount = 24000
|
||||
periods = 24
|
||||
loan = self.create_loan("fixed-principal", amount, 1, periods)
|
||||
@ -266,12 +271,18 @@ class TestLoan(TransactionCase):
|
||||
self.assertFalse(line.has_moves)
|
||||
action = (
|
||||
self.env["account.loan.generate.wizard"]
|
||||
.create({"date": fields.date.today(), "loan_type": "leasing",})
|
||||
.create(
|
||||
{
|
||||
"date": fields.date.today() + relativedelta(days=1),
|
||||
"loan_type": "leasing",
|
||||
}
|
||||
)
|
||||
.run()
|
||||
)
|
||||
self.assertTrue(line.has_invoices)
|
||||
self.assertFalse(line.has_moves)
|
||||
self.assertIn(line.invoice_ids.id, action["domain"][0][2])
|
||||
self.assertTrue(line.has_moves)
|
||||
self.assertIn(line.move_ids.id, action["domain"][0][2])
|
||||
loan.refresh()
|
||||
with self.assertRaises(UserError):
|
||||
self.env["account.loan.pay.amount"].create(
|
||||
{
|
||||
@ -291,17 +302,18 @@ class TestLoan(TransactionCase):
|
||||
+ relativedelta(months=-1),
|
||||
}
|
||||
).run()
|
||||
line.invoice_ids.action_invoice_open()
|
||||
self.assertTrue(line.move_ids)
|
||||
self.assertEqual(line.move_ids.state, "draft")
|
||||
self.assertTrue(line.has_moves)
|
||||
line.move_ids.post()
|
||||
self.assertEqual(line.move_ids.state, "posted")
|
||||
self.assertIn(
|
||||
line.move_ids.id,
|
||||
self.env["account.move"].search(loan.view_account_moves()["domain"]).ids,
|
||||
)
|
||||
self.assertEqual(
|
||||
line.invoice_ids.id,
|
||||
self.env["account.invoice"]
|
||||
.search(loan.view_account_invoices()["domain"])
|
||||
.id,
|
||||
line.move_ids.id,
|
||||
self.env["account.move"].search(loan.view_account_invoices()["domain"]).id,
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
self.env["account.loan.pay.amount"].create(
|
||||
@ -333,7 +345,7 @@ class TestLoan(TransactionCase):
|
||||
with self.assertRaises(UserError):
|
||||
line.view_process_values()
|
||||
|
||||
def test_fixed_principal_loan_auto_post(self):
|
||||
def test_fixed_principal_loan_auto_post_leasing(self):
|
||||
amount = 24000
|
||||
periods = 24
|
||||
loan = self.create_loan("fixed-principal", amount, 1, periods)
|
||||
@ -355,7 +367,7 @@ class TestLoan(TransactionCase):
|
||||
self.assertFalse(line.has_invoices)
|
||||
self.assertFalse(line.has_moves)
|
||||
self.env["account.loan.generate.wizard"].create(
|
||||
{"date": fields.date.today(), "loan_type": "leasing",}
|
||||
{"date": fields.date.today(), "loan_type": "leasing"}
|
||||
).run()
|
||||
self.assertTrue(line.has_invoices)
|
||||
self.assertTrue(line.has_moves)
|
||||
@ -383,9 +395,10 @@ class TestLoan(TransactionCase):
|
||||
for line in loan.line_ids:
|
||||
self.assertEqual(loan.state, "posted")
|
||||
line.view_process_values()
|
||||
line.move_ids.post()
|
||||
self.assertTrue(line.move_ids)
|
||||
self.assertEqual(line.move_ids.state, "posted")
|
||||
self.assertEqual(loan.state, "closed")
|
||||
|
||||
loan.refresh()
|
||||
self.assertEqual(loan.payment_amount - loan.interests_amount, amount)
|
||||
self.assertEqual(loan.pending_principal_amount, 0)
|
||||
|
||||
@ -396,7 +409,8 @@ class TestLoan(TransactionCase):
|
||||
self.post(loan)
|
||||
line = loan.line_ids.filtered(lambda r: r.sequence == 1)
|
||||
line.view_process_values()
|
||||
line.move_ids.post()
|
||||
self.assertTrue(line.move_ids)
|
||||
self.assertEqual(line.move_ids.state, "posted")
|
||||
pay = self.env["account.loan.pay.amount"].create(
|
||||
{"loan_id": loan.id, "amount": 0, "fees": 100, "date": line.date}
|
||||
)
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class AccountLoanGenerateWizard(models.TransientModel):
|
||||
@ -15,12 +15,12 @@ class AccountLoanGenerateWizard(models.TransientModel):
|
||||
default=fields.Date.context_today,
|
||||
)
|
||||
loan_type = fields.Selection(
|
||||
[("leasing", "Leasings"), ("loan", "Loans"),], required=True, default="loan"
|
||||
[("leasing", "Leasings"), ("loan", "Loans")], required=True, default="loan"
|
||||
)
|
||||
|
||||
def run_leasing(self):
|
||||
created_ids = self.env["account.loan"].generate_leasing_entries(self.date)
|
||||
action = self.env.ref("account.action_invoice_tree2")
|
||||
action = self.env.ref("account.action_move_out_invoice_type")
|
||||
result = action.read()[0]
|
||||
if len(created_ids) == 0:
|
||||
return
|
||||
@ -36,7 +36,6 @@ class AccountLoanGenerateWizard(models.TransientModel):
|
||||
result["domain"] = [("id", "in", created_ids)]
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
if self.loan_type == "leasing":
|
||||
|
@ -24,9 +24,9 @@ class AccountLoan(models.TransientModel):
|
||||
def _onchange_cancel_loan(self):
|
||||
if self.cancel_loan:
|
||||
self.amount = max(
|
||||
self.loan_id.line_ids.filtered(
|
||||
lambda r: not r.move_ids and not r.invoice_ids
|
||||
).mapped("pending_principal_amount")
|
||||
self.loan_id.line_ids.filtered(lambda r: not r.move_ids).mapped(
|
||||
"pending_principal_amount"
|
||||
)
|
||||
)
|
||||
|
||||
def new_line_vals(self, sequence):
|
||||
@ -39,16 +39,15 @@ class AccountLoan(models.TransientModel):
|
||||
"date": self.date,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
if self.loan_id.is_leasing:
|
||||
if self.loan_id.line_ids.filtered(
|
||||
lambda r: r.date < self.date and not r.invoice_ids
|
||||
lambda r: r.date <= self.date and not r.move_ids
|
||||
):
|
||||
raise UserError(_("Some invoices are not created"))
|
||||
if self.loan_id.line_ids.filtered(
|
||||
lambda r: r.date > self.date and r.invoice_ids
|
||||
lambda r: r.date > self.date and r.move_ids
|
||||
):
|
||||
raise UserError(_("Some future invoices already exists"))
|
||||
if self.loan_id.line_ids.filtered(
|
||||
@ -63,6 +62,7 @@ class AccountLoan(models.TransientModel):
|
||||
sequence = min(lines.mapped("sequence"))
|
||||
for line in lines:
|
||||
line.sequence += 1
|
||||
line.flush()
|
||||
old_line = lines.filtered(lambda r: r.sequence == sequence + 1)
|
||||
pending = old_line.pending_principal_amount
|
||||
if self.loan_id.currency_id.compare_amounts(self.amount, pending) == 1:
|
||||
|
@ -10,13 +10,13 @@ class AccountLoanPost(models.TransientModel):
|
||||
|
||||
@api.model
|
||||
def _default_journal_id(self):
|
||||
loan_id = self._context.get("default_loan_id")
|
||||
loan_id = self.env.context.get("default_loan_id")
|
||||
if loan_id:
|
||||
return self.env["account.loan"].browse(loan_id).journal_id.id
|
||||
|
||||
@api.model
|
||||
def _default_account_id(self):
|
||||
loan_id = self._context.get("default_loan_id")
|
||||
loan_id = self.env.context.get("default_loan_id")
|
||||
if loan_id:
|
||||
loan = self.env["account.loan"].browse(loan_id)
|
||||
if loan.is_leasing:
|
||||
@ -28,10 +28,10 @@ class AccountLoanPost(models.TransientModel):
|
||||
|
||||
loan_id = fields.Many2one("account.loan", required=True, readonly=True,)
|
||||
journal_id = fields.Many2one(
|
||||
"account.journal", required=True, default=_default_journal_id
|
||||
"account.journal", required=True, default=lambda r: r._default_journal_id()
|
||||
)
|
||||
account_id = fields.Many2one(
|
||||
"account.account", required=True, default=_default_account_id
|
||||
"account.account", required=True, default=lambda r: r._default_account_id()
|
||||
)
|
||||
|
||||
def move_line_vals(self):
|
||||
@ -82,7 +82,6 @@ class AccountLoanPost(models.TransientModel):
|
||||
"line_ids": [(0, 0, vals) for vals in self.move_line_vals()],
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
if self.loan_id.state != "draft":
|
||||
|
Loading…
Reference in New Issue
Block a user