[MIG] account_payment_order: Migration to 15.0

This commit is contained in:
Marçal Isern
2021-12-14 18:53:42 +01:00
committed by Pedro M. Baeza
parent ed5c2d0c3f
commit ad9f376b29
14 changed files with 223 additions and 124 deletions

View File

@@ -6,9 +6,10 @@
# © 2016 Aselcis (<https://www.aselcis.com>).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Account Payment Order",
"version": "14.0.1.4.0",
"version": "15.0.1.0.0",
"license": "AGPL-3",
"author": "ACSONE SA/NV, "
"Therp BV, "

View File

@@ -14,16 +14,20 @@ class AccountJournal(models.Model):
compute="_compute_outbound_payment_order_only", readonly=True, store=True
)
@api.depends("inbound_payment_method_ids.payment_order_only")
@api.depends("inbound_payment_method_line_ids.payment_method_id.payment_order_only")
def _compute_inbound_payment_order_only(self):
for rec in self:
rec.inbound_payment_order_only = all(
p.payment_order_only for p in rec.inbound_payment_method_ids
p.payment_order_only
for p in rec.inbound_payment_method_line_ids.payment_method_id
)
@api.depends("outbound_payment_method_ids.payment_order_only")
@api.depends(
"outbound_payment_method_line_ids.payment_method_id.payment_order_only"
)
def _compute_outbound_payment_order_only(self):
for rec in self:
rec.outbound_payment_order_only = all(
p.payment_order_only for p in rec.outbound_payment_method_ids
p.payment_order_only
for p in rec.outbound_payment_method_line_ids.payment_method_id
)

View File

@@ -23,7 +23,6 @@ class AccountMove(models.Model):
# payment mode or company level
reference_type = fields.Selection(
selection=[("none", "Free Reference"), ("structured", "Structured Reference")],
string="Reference Type",
readonly=True,
states={"draft": [("readonly", False)]},
default="none",
@@ -102,18 +101,20 @@ class AccountMove(models.Model):
if new_payorder:
move.message_post(
body=_(
"%d payment lines added to the new draft payment "
"order %s which has been automatically created."
"%(count)d payment lines added to the new draft payment "
"order %(name)s which has been automatically created.",
count=count,
name=payorder.name,
)
% (count, payorder.name)
)
else:
move.message_post(
body=_(
"%d payment lines added to the existing draft "
"payment order %s."
"%(count)d payment lines added to the existing draft "
"payment order %(name)s.",
count=count,
name=payorder.name,
)
% (count, payorder.name)
)
action = self.env["ir.actions.act_window"]._for_xml_id(
"account_payment_order.account_payment_order_%s_action"

View File

@@ -11,29 +11,33 @@ class AccountPayment(models.Model):
res = super()._get_default_journal()
return res.filtered(lambda journal: not journal.inbound_payment_order_only)
@api.depends(
"payment_type",
"journal_id.inbound_payment_method_ids",
"journal_id.outbound_payment_method_ids",
)
def _compute_payment_method_fields(self):
res = super()._compute_payment_method_fields()
@api.depends("payment_type", "journal_id")
def _compute_payment_method_line_fields(self):
res = super()._compute_payment_method_line_fields()
for pay in self:
if pay.payment_type == "inbound":
pay.available_payment_method_ids = (
pay.journal_id.inbound_payment_method_ids.filtered(
lambda m: not m.payment_order_only
)
)
else:
pay.available_payment_method_ids = (
pay.journal_id.outbound_payment_method_ids.filtered(
lambda m: not m.payment_order_only
)
)
pay.hide_payment_method = (
len(pay.available_payment_method_ids) == 1
and pay.available_payment_method_ids.code == "manual"
pay.available_payment_method_line_ids = (
pay.journal_id._get_available_payment_method_lines(
pay.payment_type
).filtered(lambda x: not x.payment_method_id.payment_order_only)
)
to_exclude = self._get_payment_method_codes_to_exclude()
if to_exclude:
pay.available_payment_method_line_ids = (
pay.available_payment_method_line_ids.filtered(
lambda x: x.code not in to_exclude
)
)
if (
pay.payment_method_line_id.id
not in pay.available_payment_method_line_ids.ids
):
# In some cases, we could be linked to a payment method
# line that has been unlinked from the journal.
# In such cases, we want to show it on the payment.
pay.hide_payment_method_line = False
else:
pay.hide_payment_method_line = (
len(pay.available_payment_method_line_ids) == 1
and pay.available_payment_method_line_ids.code == "manual"
)
return res

View File

@@ -29,7 +29,6 @@ class AccountPaymentOrder(models.Model):
)
payment_type = fields.Selection(
selection=[("inbound", "Inbound"), ("outbound", "Outbound")],
string="Payment Type",
readonly=True,
required=True,
)
@@ -180,10 +179,11 @@ class AccountPaymentOrder(models.Model):
):
raise ValidationError(
_(
"The payment type (%s) is not the same as the payment "
"type of the payment mode (%s)"
"The payment type (%(ptype)s) is not the same as the payment "
"type of the payment mode (%(pmode)s)",
ptype=order.payment_type,
pmode=order.payment_mode_id.payment_type,
)
% (order.payment_type, order.payment_mode_id.payment_type)
)
@api.constrains("date_scheduled")
@@ -194,10 +194,11 @@ class AccountPaymentOrder(models.Model):
if order.date_scheduled < today:
raise ValidationError(
_(
"On payment order %s, the Payment Execution Date "
"is in the past (%s)."
"On payment order %(porder)s, the Payment Execution Date "
"is in the past (%(exedate)s).",
porder=order.name,
exedate=order.date_scheduled,
)
% (order.name, order.date_scheduled)
)
@api.depends("payment_line_ids", "payment_line_ids.amount_company_currency")
@@ -327,16 +328,14 @@ class AccountPaymentOrder(models.Model):
):
raise UserError(
_(
"The payment mode '%s' has the option "
"The payment mode '%(pmode)s' has the option "
"'Disallow Debit Before Maturity Date'. The "
"payment line %s has a maturity date %s "
"which is after the computed payment date %s."
)
% (
order.payment_mode_id.name,
payline.name,
payline.ml_maturity_date,
requested_date,
"payment line %(pline)s has a maturity date %(mdate)s "
"which is after the computed payment date %(pdate)s.",
pmode=order.payment_mode_id.name,
pline=payline.name,
mdate=payline.ml_maturity_date,
pdate=requested_date,
)
)
# Write requested_date on 'date' field of payment line
@@ -366,8 +365,12 @@ class AccountPaymentOrder(models.Model):
# Block if a bank payment line is <= 0
if paydict["total"] <= 0:
raise UserError(
_("The amount for Partner '%s' is negative " "or null (%.2f) !")
% (paydict["paylines"][0].partner_id.name, paydict["total"])
_(
"The amount for Partner '%(partner)s' is negative "
"or null (%(amount).2f) !",
partner=paydict["paylines"][0].partner_id.name,
amount=paydict["total"],
)
)
vals = self._prepare_bank_payment_line(paydict["paylines"])
bplo.create(vals)
@@ -460,10 +463,22 @@ class AccountPaymentOrder(models.Model):
self, amount_company_currency, amount_payment_currency, bank_lines
):
vals = {}
if self.payment_type == "outbound":
account_id = self.journal_id.payment_credit_account_id.id
else:
account_id = self.journal_id.payment_debit_account_id.id
payment_method = self.payment_mode_id.payment_method_id
account_id = False
if self.payment_type == "inbound":
account_id = (
self.journal_id.inbound_payment_method_line_ids.filtered(
lambda x: x.payment_method_id == payment_method
).payment_account_id.id
or self.journal_id.company_id.account_journal_payment_debit_account_id.id
)
elif self.payment_type == "outbound":
account_id = (
self.journal_id.outbound_payment_method_line_ids.filtered(
lambda x: x.payment_method_id == payment_method
).payment_account_id.id
or self.journal_id.company_id.account_journal_payment_credit_account_id.id
)
partner_id = False
for index, bank_line in enumerate(bank_lines):

View File

@@ -70,7 +70,7 @@ class BankPaymentLine(models.Model):
communication_type = fields.Selection(
related="payment_line_ids.communication_type", readonly=True
)
communication = fields.Char(string="Communication", required=True, readonly=True)
communication = fields.Char(required=True, readonly=True)
company_id = fields.Many2one(
comodel_name="res.company",
related="order_id.payment_mode_id.company_id",
@@ -160,26 +160,29 @@ class BankPaymentLine(models.Model):
raise UserError(
_(
"Can not reconcile: no move line for "
"payment line %s of partner '%s'."
"payment line %(line)s of partner '%(partner)s'.",
line=payment_line.name,
partner=payment_line.partner_id.name,
)
% (payment_line.name, payment_line.partner_id.name)
)
if payment_line.move_line_id.reconciled:
raise UserError(
_("Move line '%s' of partner '%s' has already " "been reconciled")
% (payment_line.move_line_id.name, payment_line.partner_id.name)
_(
"Move line '%(line)s' of partner '%(partner)s' has already "
"been reconciled",
line=payment_line.move_line_id.name,
partner=payment_line.partner_id.name,
)
)
if payment_line.move_line_id.account_id != transit_mline.account_id:
raise UserError(
_(
"For partner '%s', the account of the account "
"move line to pay (%s) is different from the "
"account of of the transit move line (%s)."
)
% (
payment_line.move_line_id.partner_id.name,
payment_line.move_line_id.account_id.code,
transit_mline.account_id.code,
"For partner '%(partner)s', the account of the account "
"move line to pay (%(line1)s) is different from the "
"account of of the transit move line (%(line2)s).",
partner=payment_line.move_line_id.partner_id.name,
line1=payment_line.move_line_id.account_id.code,
line2=transit_mline.account_id.code,
)
)
@@ -194,8 +197,8 @@ class BankPaymentLine(models.Model):
raise UserError(
_(
"Cannot delete a payment order line whose payment order is"
" in state '%s'. You need to cancel it first."
" in state '%(state)s'. You need to cancel it first.",
state=order_state,
)
% order_state
)
return super(BankPaymentLine, self).unlink()

View File

@@ -14,10 +14,11 @@ class ResBank(models.Model):
if bank.bic and len(bank.bic) not in (8, 11):
raise ValidationError(
_(
"A valid BIC contains 8 or 11 characters. The BIC '%s' "
"contains %d characters, so it is not valid."
"A valid BIC contains 8 or 11 characters. The BIC '%(bic)s' "
"contains %(num)d characters, so it is not valid.",
bic=bank.bic,
num=len(bank.bic),
)
% (bank.bic, len(bank.bic))
)

View File

@@ -27,3 +27,4 @@
* `Open Source Integrators <https://www.opensourceintegrators.com>`_:
* Ammar Officewala <aofficewala@opensourceintegrators.com>
* Marçal Isern <marsal.isern@qubiq.es>

View File

@@ -1,7 +1,9 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from unittest.mock import patch
from odoo.addons.account.models.account_payment_method import AccountPaymentMethod
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
@@ -9,6 +11,18 @@ class TestAccountPayment(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
Method_get_payment_method_information = (
AccountPaymentMethod._get_payment_method_information
)
def _get_payment_method_information(self):
res = Method_get_payment_method_information(self)
res["IN"] = {"mode": "multi", "domain": [("type", "=", "bank")]}
res["IN2"] = {"mode": "multi", "domain": [("type", "=", "bank")]}
res["OUT"] = {"mode": "multi", "domain": [("type", "=", "bank")]}
return res
cls.company = cls.company_data["company"]
cls.env.user.company_ids += cls.company
@@ -19,38 +33,38 @@ class TestAccountPayment(AccountTestInvoicingCommon):
# INSTANCES
# Payment methods
cls.inbound_payment_method_01 = cls.payment_method_model.create(
{
"name": "inbound",
"code": "IN",
"payment_type": "inbound",
}
)
cls.inbound_payment_method_02 = cls.inbound_payment_method_01.copy(
{
"name": "inbound 2",
"code": "IN2",
}
)
cls.outbound_payment_method_01 = cls.payment_method_model.create(
{
"name": "outbound",
"code": "OUT",
"payment_type": "outbound",
}
)
# Journals
cls.bank_journal = cls.company_data["default_journal_bank"]
cls.bank_journal.inbound_payment_method_ids = [
(
6,
0,
[cls.inbound_payment_method_01.id, cls.inbound_payment_method_02.id],
with patch.object(
AccountPaymentMethod,
"_get_payment_method_information",
_get_payment_method_information,
):
cls.inbound_payment_method_01 = cls.payment_method_model.create(
{
"name": "inbound",
"code": "IN",
"payment_type": "inbound",
}
)
]
cls.bank_journal.outbound_payment_method_ids = [
(6, 0, [cls.outbound_payment_method_01.id])
]
cls.inbound_payment_method_02 = cls.inbound_payment_method_01.copy(
{
"name": "inbound 2",
"code": "IN2",
"payment_type": "inbound",
}
)
cls.outbound_payment_method_01 = cls.payment_method_model.create(
{
"name": "outbound",
"code": "OUT",
"payment_type": "outbound",
}
)
# Journals
cls.manual_in = cls.env.ref("account.account_payment_method_manual_in")
cls.manual_out = cls.env.ref("account.account_payment_method_manual_out")
cls.bank_journal = cls.company_data["default_journal_bank"]
def test_account_payment_01(self):
self.assertFalse(self.inbound_payment_method_01.payment_order_only)
@@ -63,6 +77,7 @@ class TestAccountPayment(AccountTestInvoicingCommon):
self.inbound_payment_method_02.payment_order_only = True
self.assertTrue(self.inbound_payment_method_01.payment_order_only)
self.assertTrue(self.inbound_payment_method_02.payment_order_only)
self.manual_in.payment_order_only = True
self.assertTrue(self.bank_journal.inbound_payment_order_only)
def test_account_payment_02(self):
@@ -70,6 +85,11 @@ class TestAccountPayment(AccountTestInvoicingCommon):
self.assertFalse(self.bank_journal.outbound_payment_order_only)
self.outbound_payment_method_01.payment_order_only = True
self.assertTrue(self.outbound_payment_method_01.payment_order_only)
payment_method_id = (
self.bank_journal.outbound_payment_method_line_ids.payment_method_id
)
payment_method_id.payment_order_only = True
self.assertTrue(self.bank_journal.outbound_payment_order_only)
def test_account_payment_03(self):
@@ -90,7 +110,13 @@ class TestAccountPayment(AccountTestInvoicingCommon):
journals = new_account_payment._get_default_journal()
self.assertIn(self.bank_journal, journals)
# check payment methods
payment_methods = new_account_payment.available_payment_method_ids.ids
payment_methods = (
new_account_payment.available_payment_method_line_ids.filtered(
lambda x: x.payment_type == "inbound"
)
.mapped("payment_method_id")
.ids
)
self.assertIn(self.inbound_payment_method_01.id, payment_methods)
self.assertIn(self.inbound_payment_method_02.id, payment_methods)
# Set one payment method of the bank journal 'payment order only'
@@ -99,20 +125,43 @@ class TestAccountPayment(AccountTestInvoicingCommon):
journals = new_account_payment._get_default_journal()
self.assertIn(self.bank_journal, journals)
# check payment methods
new_account_payment._compute_payment_method_fields()
payment_methods = new_account_payment.available_payment_method_ids.ids
new_account_payment2 = self.account_payment_model.with_context(
default_company_id=self.company.id
).new(
{
"journal_id": self.bank_journal.id,
"payment_type": "inbound",
"amount": 1,
"company_id": self.company.id,
}
)
payment_methods = new_account_payment2.available_payment_method_line_ids.mapped(
"payment_method_id"
).ids
self.assertNotIn(self.inbound_payment_method_01.id, payment_methods)
self.assertIn(self.inbound_payment_method_02.id, payment_methods)
# Set all payment methods of the bank journal 'payment order only'
self.inbound_payment_method_02.payment_order_only = True
self.assertTrue(self.inbound_payment_method_01.payment_order_only)
self.assertTrue(self.inbound_payment_method_02.payment_order_only)
self.manual_in.payment_order_only = True
self.assertTrue(self.bank_journal.inbound_payment_order_only)
# check journals
journals = new_account_payment._get_default_journal()
self.assertNotIn(self.bank_journal, journals)
# check payment methods
new_account_payment._compute_payment_method_fields()
payment_methods = new_account_payment.available_payment_method_ids.ids
new_account_payment3 = self.account_payment_model.with_context(
default_company_id=self.company.id
).new(
{
"journal_id": self.bank_journal.id,
"payment_type": "inbound",
"amount": 1,
"company_id": self.company.id,
}
)
payment_methods = new_account_payment3.available_payment_method_line_ids.mapped(
"payment_method_id"
).ids
self.assertNotIn(self.inbound_payment_method_01.id, payment_methods)
self.assertNotIn(self.inbound_payment_method_02.id, payment_methods)

View File

@@ -1,13 +1,28 @@
# © 2017 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from unittest.mock import patch
from odoo.tests.common import TransactionCase
from odoo.addons.account.models.account_payment_method import AccountPaymentMethod
class TestPaymentMode(TransactionCase):
def setUp(self):
super(TestPaymentMode, self).setUp()
Method_get_payment_method_information = (
AccountPaymentMethod._get_payment_method_information
)
def _get_payment_method_information(self):
res = Method_get_payment_method_information(self)
res["IN"] = {"mode": "multi", "domain": [("type", "=", "bank")]}
res["IN2"] = {"mode": "multi", "domain": [("type", "=", "bank")]}
res["electronic_out"] = {"mode": "multi", "domain": [("type", "=", "bank")]}
return res
# Company
self.company = self.env.ref("base.main_company")
@@ -28,13 +43,19 @@ class TestPaymentMode(TransactionCase):
self.manual_in = self.env.ref("account.account_payment_method_manual_in")
self.electronic_out = self.env["account.payment.method"].create(
{
"name": "Electronic Out",
"code": "electronic_out",
"payment_type": "outbound",
}
)
with patch.object(
AccountPaymentMethod,
"_get_payment_method_information",
_get_payment_method_information,
):
self.electronic_out = self.env["account.payment.method"].create(
{
"name": "Electronic Out",
"code": "electronic_out",
"payment_type": "outbound",
}
)
self.payment_mode_c1 = self.env["account.payment.mode"].create(
{

View File

@@ -51,7 +51,7 @@
<field name="name">account.payment.line.tree</field>
<field name="model">account.payment.line</field>
<field name="arch" type="xml">
<tree string="Payment Lines">
<tree>
<field
name="order_id"
invisible="not context.get('account_payment_line_main_view')"

View File

@@ -141,7 +141,7 @@
<field name="name">account.payment.order.tree</field>
<field name="model">account.payment.order</field>
<field name="arch" type="xml">
<tree string="Payment Orders">
<tree>
<field name="name" decoration-bf="1" />
<field name="payment_mode_id" />
<field name="journal_id" />

View File

@@ -39,7 +39,7 @@
<field name="name">bank.payment.line.tree</field>
<field name="model">bank.payment.line</field>
<field name="arch" type="xml">
<tree string="Bank Payment Lines" create="false">
<tree create="false">
<field
name="order_id"
invisible="not context.get('bank_payment_line_main_view')"

View File

@@ -33,11 +33,10 @@ class AccountPaymentLineCreate(models.TransientModel):
string="Type of Date Filter",
required=True,
)
due_date = fields.Date(string="Due Date")
move_date = fields.Date(string="Move Date", default=fields.Date.context_today)
due_date = fields.Date()
move_date = fields.Date(default=fields.Date.context_today)
payment_mode = fields.Selection(
selection=[("same", "Same"), ("same_or_null", "Same or Empty"), ("any", "Any")],
string="Payment Mode",
)
move_line_ids = fields.Many2many(
comodel_name="account.move.line", string="Move Lines"