mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
[IMP] account_payment_partner: Add refund_payment_mode_id to assign any payment mode to set auto-compute in reverse moves (in_refund and out_refund)
This commit is contained in:
committed by
Thomas Binsfeld
parent
7cde1e1f34
commit
17b8ca575f
@@ -1,6 +1,7 @@
|
||||
# Copyright 2014 Akretion - Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# Copyright 2014 Tecnativa - Pedro M. Baeza
|
||||
# Copyright 2018 Tecnativa - Carlos Dauden
|
||||
# Copyright 2021 Tecnativa - Víctor Martínez
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
{
|
||||
@@ -9,7 +10,7 @@
|
||||
"category": "Banking addons",
|
||||
"license": "AGPL-3",
|
||||
"summary": "Adds payment mode on partners and invoices",
|
||||
"author": "Akretion, " "Tecnativa, " "Odoo Community Association (OCA)",
|
||||
"author": "Akretion, Tecnativa, Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/bank-payment",
|
||||
"depends": ["account_payment_mode"],
|
||||
"data": [
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Copyright 2014-16 Akretion - Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# Copyright 2014 Serv. Tecnol. Avanzados - Pedro M. Baeza
|
||||
# Copyright 2021 Tecnativa - Víctor Martínez
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
@@ -57,14 +58,26 @@ class AccountMove(models.Model):
|
||||
for move in self:
|
||||
move.payment_mode_id = False
|
||||
if move.partner_id:
|
||||
if move.move_type == "in_invoice":
|
||||
move.payment_mode_id = move.with_company(
|
||||
move.company_id.id
|
||||
).partner_id.supplier_payment_mode_id
|
||||
elif move.move_type == "out_invoice":
|
||||
move.payment_mode_id = move.with_company(
|
||||
move.company_id.id
|
||||
).partner_id.customer_payment_mode_id
|
||||
partner = move.with_context(force_company=move.company_id.id).partner_id
|
||||
if move.type == "in_invoice":
|
||||
move.payment_mode_id = partner.supplier_payment_mode_id
|
||||
elif move.type == "out_invoice":
|
||||
move.payment_mode_id = partner.customer_payment_mode_id
|
||||
elif (
|
||||
move.type in ["out_refund", "in_refund"] and move.reversed_entry_id
|
||||
):
|
||||
move.payment_mode_id = (
|
||||
move.reversed_entry_id.payment_mode_id.refund_payment_mode_id
|
||||
)
|
||||
elif not move.reversed_entry_id:
|
||||
if move.type == "out_refund":
|
||||
move.payment_mode_id = (
|
||||
partner.customer_payment_mode_id.refund_payment_mode_id
|
||||
)
|
||||
elif move.type == "in_refund":
|
||||
move.payment_mode_id = (
|
||||
partner.supplier_payment_mode_id.refund_payment_mode_id
|
||||
)
|
||||
|
||||
@api.depends("partner_id", "payment_mode_id")
|
||||
def _compute_partner_bank(self):
|
||||
@@ -90,15 +103,11 @@ class AccountMove(models.Model):
|
||||
bank_id = get_bank_id()
|
||||
move.partner_bank_id = bank_id
|
||||
|
||||
# I think copying payment mode from invoice to refund by default
|
||||
# is a good idea because the most common way of "paying" a refund is to
|
||||
# deduct it on the payment of the next invoice (and OCA/bank-payment
|
||||
# allows to have negative payment lines since March 2016)
|
||||
def _reverse_move_vals(self, default_values, cancel=True):
|
||||
move_vals = super()._reverse_move_vals(default_values, cancel=cancel)
|
||||
move_vals["payment_mode_id"] = self.payment_mode_id.id
|
||||
if self.move_type == "in_invoice":
|
||||
move_vals["partner_bank_id"] = self.partner_bank_id.id
|
||||
move_vals["payment_mode_id"] = self.payment_mode_id.refund_payment_mode_id.id
|
||||
if self.type == "in_invoice":
|
||||
move_vals["invoice_partner_bank_id"] = self.invoice_partner_bank_id.id
|
||||
return move_vals
|
||||
|
||||
def partner_banks_to_show(self):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Copyright 2017 ForgeFlow S.L.
|
||||
# Copyright 2018 Carlos Dauden - Tecnativa <carlos.dauden@tecnativa.com>
|
||||
# Copyright 2018 Tecnativa - Carlos Dauden
|
||||
# Copyright 2021 Tecnativa - Víctor Martínez
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
@@ -24,6 +25,13 @@ class AccountPaymentMode(models.Model):
|
||||
show_bank_account_chars = fields.Integer(
|
||||
string="# of digits for customer bank account"
|
||||
)
|
||||
refund_payment_mode_id = fields.Many2one(
|
||||
comodel_name="account.payment.mode",
|
||||
domain="[('payment_type', '!=', payment_type)]",
|
||||
string="Payment mode for refunds",
|
||||
help="This payment mode will be used when doing "
|
||||
"refunds coming from the current payment mode.",
|
||||
)
|
||||
|
||||
@api.constrains("company_id")
|
||||
def account_invoice_company_constrains(self):
|
||||
|
||||
@@ -9,13 +9,13 @@ class ResPartner(models.Model):
|
||||
_inherit = "res.partner"
|
||||
|
||||
supplier_payment_mode_id = fields.Many2one(
|
||||
"account.payment.mode",
|
||||
comodel_name="account.payment.mode",
|
||||
company_dependent=True,
|
||||
domain="[('payment_type', '=', 'outbound')]",
|
||||
help="Select the default payment mode for this supplier.",
|
||||
)
|
||||
customer_payment_mode_id = fields.Many2one(
|
||||
"account.payment.mode",
|
||||
comodel_name="account.payment.mode",
|
||||
company_dependent=True,
|
||||
domain="[('payment_type', '=', 'inbound')]",
|
||||
help="Select the default payment mode for this customer.",
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
* Angel Moya <angel.moya@domatix.com>
|
||||
* `Tecnativa <https://www.tecnativa.com>`_:
|
||||
|
||||
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
|
||||
* Carlos Dauden <carlos.dauden@tecnativa.com>
|
||||
* Pedro M. Baeza
|
||||
* Carlos Dauden
|
||||
* Víctor Martínez
|
||||
* `DynApps <https://www.dynapps.be>`_:
|
||||
|
||||
* Raf Ven <raf.ven@dynapps.be>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# Copyright 2017 ForgeFlow S.L.
|
||||
# Copyright 2021 Tecnativa - Víctor Martínez
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||
|
||||
from odoo import _, fields
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.tests import common
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tests.common import Form, SavepointCase
|
||||
|
||||
|
||||
class TestAccountPaymentPartner(common.SavepointCase):
|
||||
class TestAccountPaymentPartner(SavepointCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
@@ -20,6 +21,7 @@ class TestAccountPaymentPartner(common.SavepointCase):
|
||||
# Refs
|
||||
cls.company = cls.env.ref("base.main_company")
|
||||
cls.acct_type_payable = cls.env.ref("account.data_account_type_payable")
|
||||
cls.acct_type_receivable = cls.env.ref("account.data_account_type_receivable")
|
||||
cls.acct_type_expenses = cls.env.ref("account.data_account_type_expenses")
|
||||
|
||||
cls.company_2 = cls.env["res.company"].create({"name": "Company 2"})
|
||||
@@ -106,9 +108,13 @@ class TestAccountPaymentPartner(common.SavepointCase):
|
||||
"payment_method_id": cls.manual_in.id,
|
||||
"company_id": cls.company.id,
|
||||
"fixed_journal_id": cls.journal_c1.id,
|
||||
"refund_payment_mode_id": cls.supplier_payment_mode.id,
|
||||
"variable_journal_ids": [(6, 0, [cls.journal_c1.id])],
|
||||
}
|
||||
)
|
||||
cls.supplier_payment_mode.write(
|
||||
{"refund_payment_mode_id": cls.customer_payment_mode.id}
|
||||
)
|
||||
|
||||
cls.customer = (
|
||||
cls.env["res.partner"]
|
||||
@@ -186,33 +192,18 @@ class TestAccountPaymentPartner(common.SavepointCase):
|
||||
}
|
||||
)
|
||||
|
||||
def _create_invoice(self):
|
||||
invoice = self.move_model.create(
|
||||
{
|
||||
"partner_id": self.supplier.id,
|
||||
"journal_id": self.journal_purchase.id,
|
||||
"move_type": "in_invoice",
|
||||
"invoice_date": fields.Date.today(),
|
||||
"company_id": self.company.id,
|
||||
"payment_mode_id": self.env.ref(
|
||||
"account_payment_mode.payment_mode_outbound_ct1"
|
||||
).id,
|
||||
"invoice_line_ids": [
|
||||
(
|
||||
0,
|
||||
None,
|
||||
{
|
||||
"product_id": self.env.ref("product.product_product_4").id,
|
||||
"quantity": 1.0,
|
||||
"price_unit": 100.0,
|
||||
"name": "product that cost 100",
|
||||
"account_id": self.invoice_line_account.id,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
def _create_invoice(self, default_type, partner):
|
||||
move_form = Form(
|
||||
self.env["account.move"].with_context(default_type=default_type)
|
||||
)
|
||||
return invoice
|
||||
move_form.partner_id = partner
|
||||
with move_form.invoice_line_ids.new() as line_form:
|
||||
line_form.product_id = self.env.ref("product.product_product_4")
|
||||
line_form.name = "product that cost 100"
|
||||
line_form.quantity = 1.0
|
||||
line_form.price_unit = 100.0
|
||||
line_form.account_id = self.invoice_line_account
|
||||
return move_form.save()
|
||||
|
||||
def test_create_partner(self):
|
||||
customer = (
|
||||
@@ -282,14 +273,42 @@ class TestAccountPaymentPartner(common.SavepointCase):
|
||||
self.assertEqual(invoice.payment_mode_id, self.payment_mode_model)
|
||||
self.assertEqual(invoice.partner_bank_id, self.partner_bank_model)
|
||||
|
||||
def test_invoice_create(self):
|
||||
invoice = self._create_invoice()
|
||||
def test_invoice_create_in_invoice(self):
|
||||
invoice = self._create_invoice(default_type="in_invoice", partner=self.supplier)
|
||||
invoice.action_post()
|
||||
aml = invoice.line_ids.filtered(
|
||||
lambda l: l.account_id.user_type_id == self.acct_type_payable
|
||||
)
|
||||
self.assertEqual(invoice.payment_mode_id, aml[0].payment_mode_id)
|
||||
|
||||
def test_invoice_create_out_invoice(self):
|
||||
invoice = self._create_invoice(
|
||||
default_type="out_invoice", partner=self.customer
|
||||
)
|
||||
invoice.action_post()
|
||||
aml = invoice.line_ids.filtered(
|
||||
lambda l: l.account_id.user_type_id == self.acct_type_receivable
|
||||
)
|
||||
self.assertEquals(invoice.payment_mode_id, aml[0].payment_mode_id)
|
||||
|
||||
def test_invoice_create_out_refund(self):
|
||||
self.manual_out.bank_account_required = False
|
||||
invoice = self._create_invoice(default_type="out_refund", partner=self.customer)
|
||||
invoice.action_post()
|
||||
self.assertEquals(
|
||||
invoice.payment_mode_id,
|
||||
self.customer.customer_payment_mode_id.refund_payment_mode_id,
|
||||
)
|
||||
|
||||
def test_invoice_create_in_refund(self):
|
||||
self.manual_in.bank_account_required = False
|
||||
invoice = self._create_invoice(default_type="in_refund", partner=self.supplier)
|
||||
invoice.action_post()
|
||||
self.assertEquals(
|
||||
invoice.payment_mode_id,
|
||||
self.supplier.supplier_payment_mode_id.refund_payment_mode_id,
|
||||
)
|
||||
|
||||
def test_invoice_constrains(self):
|
||||
with self.assertRaises(UserError):
|
||||
self.move_model.create(
|
||||
@@ -351,9 +370,39 @@ class TestAccountPaymentPartner(common.SavepointCase):
|
||||
with self.assertRaises(UserError):
|
||||
self.supplier_payment_mode.company_id = self.company_2
|
||||
|
||||
def test_invoice_refund(self):
|
||||
invoice = self._create_invoice()
|
||||
invoice.partner_bank_id = False
|
||||
def test_invoice_in_refund(self):
|
||||
invoice = self._create_invoice(default_type="in_invoice", partner=self.supplier)
|
||||
invoice.invoice_partner_bank_id = False
|
||||
invoice.action_post()
|
||||
# Lets create a refund invoice for invoice_1.
|
||||
# I refund the invoice Using Refund Button.
|
||||
refund_invoice_wizard = (
|
||||
self.env["account.move.reversal"]
|
||||
.with_context(
|
||||
{
|
||||
"active_ids": [invoice.id],
|
||||
"active_id": invoice.id,
|
||||
"active_model": "account.move",
|
||||
}
|
||||
)
|
||||
.create({"refund_method": "refund", "reason": "reason test create"})
|
||||
)
|
||||
refund_invoice = self.move_model.browse(
|
||||
refund_invoice_wizard.reverse_moves()["res_id"]
|
||||
)
|
||||
self.assertEquals(
|
||||
refund_invoice.payment_mode_id,
|
||||
invoice.payment_mode_id.refund_payment_mode_id,
|
||||
)
|
||||
self.assertEquals(
|
||||
refund_invoice.invoice_partner_bank_id, invoice.invoice_partner_bank_id
|
||||
)
|
||||
|
||||
def test_invoice_out_refund(self):
|
||||
invoice = self._create_invoice(
|
||||
default_type="out_invoice", partner=self.customer
|
||||
)
|
||||
invoice.invoice_partner_bank_id = False
|
||||
invoice.action_post()
|
||||
# Lets create a refund invoice for invoice_1.
|
||||
# I refund the invoice Using Refund Button.
|
||||
@@ -372,8 +421,13 @@ class TestAccountPaymentPartner(common.SavepointCase):
|
||||
refund_invoice_wizard.reverse_moves()["res_id"]
|
||||
)
|
||||
|
||||
self.assertEqual(refund_invoice.payment_mode_id, invoice.payment_mode_id)
|
||||
self.assertEqual(refund_invoice.partner_bank_id, invoice.partner_bank_id)
|
||||
self.assertEquals(
|
||||
refund_invoice.payment_mode_id,
|
||||
invoice.payment_mode_id.refund_payment_mode_id,
|
||||
)
|
||||
self.assertEquals(
|
||||
refund_invoice.invoice_partner_bank_id, invoice.invoice_partner_bank_id
|
||||
)
|
||||
|
||||
def test_partner(self):
|
||||
self.customer.write({"customer_payment_mode_id": self.customer_payment_mode.id})
|
||||
@@ -387,17 +441,27 @@ class TestAccountPaymentPartner(common.SavepointCase):
|
||||
)
|
||||
self.assertEqual(customer_invoice.payment_mode_id, self.customer_payment_mode)
|
||||
|
||||
self.assertEqual(self.supplier_invoice.partner_bank_id, self.supplier_bank)
|
||||
vals = {"partner_id": False, "move_type": "out_invoice"}
|
||||
self.assertEqual(
|
||||
self.supplier_invoice.invoice_partner_bank_id, self.supplier_bank
|
||||
)
|
||||
vals = {"partner_id": self.customer.id, "type": "out_refund"}
|
||||
invoice = self.move_model.new(vals)
|
||||
self.assertEquals(invoice.payment_mode_id, self.supplier_payment_mode)
|
||||
vals = {"partner_id": self.supplier.id, "type": "in_refund"}
|
||||
invoice = self.move_model.new(vals)
|
||||
self.assertEquals(invoice.payment_mode_id, self.customer_payment_mode)
|
||||
vals = {"partner_id": False, "type": "out_invoice"}
|
||||
invoice = self.move_model.new(vals)
|
||||
self.assertFalse(invoice.payment_mode_id)
|
||||
vals = {
|
||||
"partner_id": False,
|
||||
"move_type": "in_invoice",
|
||||
"invoice_date": fields.Date.today(),
|
||||
}
|
||||
vals = {"partner_id": False, "type": "out_refund"}
|
||||
invoice = self.move_model.new(vals)
|
||||
self.assertFalse(invoice.partner_bank_id)
|
||||
self.assertFalse(invoice.invoice_partner_bank_id)
|
||||
vals = {"partner_id": False, "type": "in_invoice"}
|
||||
invoice = self.move_model.new(vals)
|
||||
self.assertFalse(invoice.invoice_partner_bank_id)
|
||||
vals = {"partner_id": False, "type": "in_refund"}
|
||||
invoice = self.move_model.new(vals)
|
||||
self.assertFalse(invoice.invoice_partner_bank_id)
|
||||
|
||||
def test_onchange_payment_mode_id(self):
|
||||
mode = self.supplier_payment_mode
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
<field name="model">account.payment.mode</field>
|
||||
<field name="inherit_id" ref="account_payment_mode.account_payment_mode_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="variable_journal_ids" position="before">
|
||||
<field name="refund_payment_mode_id" />
|
||||
</field>
|
||||
<group name="note" position="before">
|
||||
<group string="Show bank account in invoice report">
|
||||
<group>
|
||||
|
||||
Reference in New Issue
Block a user