Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions account_payment_line/README.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=========================
Payment Counterpart Lines
=========================
Expand All @@ -17,7 +13,7 @@ Payment Counterpart Lines
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--payment-lightgray.png?logo=github
Expand All @@ -43,6 +39,21 @@ Add tool to proposal of payment distributions, ordering by due date
.. contents::
:local:

Configuration
=============

By default, counterpart lines let you pick any partner, so you can move
balances between partners.

If you want to forbid that and make sure a payment only applies invoices
of the partner set on its header, go to **Invoicing / Settings** and
enable **Restrict counterpart lines to payment partner**.

The setting is company dependent and disabled by default, so it does not
change the current behavior unless you activate it. Once enabled, the
partner of the counterpart lines is limited to the commercial entity of
the payment partner, both in the interface and on save.

Usage
=====

Expand Down Expand Up @@ -76,6 +87,7 @@ Contributors

- Christopher Ormaza. <chris.ormaza@forgeflow.com>
- Do Anh Duy <duyda@trobz.com>
- Ricardo Jara (Spearhead) <rvjaraj@gmail.com>

Maintainers
-----------
Expand Down
3 changes: 2 additions & 1 deletion account_payment_line/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"author": "ForgeFlow S.L., Odoo Community Association (OCA)",
"website": "https://github.com/OCA/account-payment",
"category": "Account",
"version": "18.0.1.0.2",
"version": "18.0.1.1.0",
"license": "AGPL-3",
"depends": ["account_payment"],
"data": [
"security/ir.model.access.csv",
"views/res_config_settings_views.xml",
"views/account_payment_views.xml",
],
"maintainers": ["ChrisOForgeFlow"],
Expand Down
2 changes: 2 additions & 0 deletions account_payment_line/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from . import res_company
from . import res_config_settings
from . import counterpart_line
from . import account_payment
from . import account_move
56 changes: 55 additions & 1 deletion account_payment_line/models/account_payment.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright 2022 ForgeFlow, S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from odoo import Command, fields, models
from odoo import Command, api, fields, models
from odoo.exceptions import ValidationError


Expand All @@ -20,6 +20,16 @@ class AccountPayment(models.Model):
string="Write-off Account",
domain="[('deprecated', '=', False), ('company_ids', '=', company_id)]",
)
restrict_counterpart_partner = fields.Boolean(
compute="_compute_restrict_counterpart_partner",
)

@api.depends("company_id.payment_line_restrict_counterpart_partner")
def _compute_restrict_counterpart_partner(self):
for rec in self:
rec.restrict_counterpart_partner = (
rec.company_id.payment_line_restrict_counterpart_partner
)

def _process_post_reconcile(self):
for rec in self.filtered("line_payment_counterpart_ids"):
Expand Down Expand Up @@ -290,7 +300,51 @@ class AccountPaymentCounterLine(models.Model):
payment_id = fields.Many2one(
"account.payment", string="Payment", ondelete="cascade"
)
counterpart_partner_domain = fields.Binary(
compute="_compute_counterpart_partner_domain",
help="Technical field holding the domain applied to the partner of the "
"counterpart line.",
)

def _get_onchange_fields(self):
res = super()._get_onchange_fields()
return res + ("payment_id.currency_id", "payment_id.date")

@api.depends("payment_id.partner_id", "payment_id.restrict_counterpart_partner")
def _compute_counterpart_partner_domain(self):
for rec in self:
payment = rec.payment_id
if not payment.restrict_counterpart_partner:
rec.counterpart_partner_domain = []
elif payment.partner_id:
commercial_partner = payment.partner_id.commercial_partner_id
rec.counterpart_partner_domain = [
("commercial_partner_id", "=", commercial_partner.id)
]
else:
# Restriction is on but no partner is set yet: forbid selection
# instead of offering every partner.
rec.counterpart_partner_domain = [("id", "=", False)]

@api.constrains("partner_id", "move_id", "aml_id", "payment_id")
def _check_counterpart_partner(self):
for rec in self:
payment = rec.payment_id
if not payment or not payment.restrict_counterpart_partner:
continue
payment_partner = payment.partner_id.commercial_partner_id
if not payment_partner:
continue
line_partners = (
rec.partner_id.commercial_partner_id
| rec.move_id.commercial_partner_id
| rec.aml_id.partner_id.commercial_partner_id
)
if line_partners and line_partners != payment_partner:
raise ValidationError(
self.env._(
"You can only apply counterpart lines of %(partner)s, "
"the partner set on the payment.",
partner=payment_partner.display_name,
)
)
13 changes: 13 additions & 0 deletions account_payment_line/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from odoo import fields, models


class ResCompany(models.Model):
_inherit = "res.company"

payment_line_restrict_counterpart_partner = fields.Boolean(
string="Restrict counterpart lines to payment partner",
help="When enabled, counterpart lines of a payment can only use the "
"partner set on the payment header (its commercial entity). This "
"prevents applying invoices of a partner different from the one "
"registered in the payment.",
)
10 changes: 10 additions & 0 deletions account_payment_line/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

payment_line_restrict_counterpart_partner = fields.Boolean(
related="company_id.payment_line_restrict_counterpart_partner",
readonly=False,
)
11 changes: 11 additions & 0 deletions account_payment_line/readme/CONFIGURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
By default, counterpart lines let you pick any partner, so you can move
balances between partners.

If you want to forbid that and make sure a payment only applies invoices
of the partner set on its header, go to **Invoicing / Settings** and enable
**Restrict counterpart lines to payment partner**.

The setting is company dependent and disabled by default, so it does not
change the current behavior unless you activate it. Once enabled, the
partner of the counterpart lines is limited to the commercial entity of
the payment partner, both in the interface and on save.
1 change: 1 addition & 0 deletions account_payment_line/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Christopher Ormaza. \<<chris.ormaza@forgeflow.com>\>
- Do Anh Duy \<<duyda@trobz.com>\>
- Ricardo Jara (Spearhead) \<<rvjaraj@gmail.com>\>
52 changes: 30 additions & 22 deletions account_payment_line/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<title>Payment Counterpart Lines</title>
<style type="text/css">

/*
Expand Down Expand Up @@ -360,71 +360,80 @@
</style>
</head>
<body>
<div class="document">
<div class="document" id="payment-counterpart-lines">
<h1 class="title">Payment Counterpart Lines</h1>


<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="payment-counterpart-lines">
<h1>Payment Counterpart Lines</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:c2a2fbcb3dbe0a280921e115ae1fc720c4146a7843da5c031cd40f07f44c9d9b
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-payment/tree/18.0/account_payment_line"><img alt="OCA/account-payment" src="https://img.shields.io/badge/github-OCA%2Faccount--payment-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-payment-18-0/account-payment-18-0-account_payment_line"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-payment&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-payment/tree/18.0/account_payment_line"><img alt="OCA/account-payment" src="https://img.shields.io/badge/github-OCA%2Faccount--payment-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-payment-18-0/account-payment-18-0-account_payment_line"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-payment&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module is an utility module to add lines in payment, allowing users
make more complicated cases when processing payments, split on many
invoices, set up specific write-off and adding some analytic information</p>
<p>Add tool to proposal of payment distributions, ordering by due date</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<p>By default, counterpart lines let you pick any partner, so you can move
balances between partners.</p>
<p>If you want to forbid that and make sure a payment only applies invoices
of the partner set on its header, go to <strong>Invoicing / Settings</strong> and
enable <strong>Restrict counterpart lines to payment partner</strong>.</p>
<p>The setting is company dependent and disabled by default, so it does not
change the current behavior unless you activate it. Once enabled, the
partner of the counterpart lines is limited to the commercial entity of
the payment partner, both in the interface and on save.</p>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>You can use payment distribution suggestion, and if system found moves
pending to reconcile related with partner selected, system will create
all lines trying to pay all invoices until amount remain</p>
<p>You can add manually lines, if payment don’t detect lines specified,
payment works as a normal payment</p>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-payment/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/account-payment/issues/new?body=module:%20account_payment_line%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-3">Credits</a></h2>
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-4">Authors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>ForgeFlow S.L.</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Christopher Ormaza. &lt;<a class="reference external" href="mailto:chris.ormaza&#64;forgeflow.com">chris.ormaza&#64;forgeflow.com</a>&gt;</li>
<li>Do Anh Duy &lt;<a class="reference external" href="mailto:duyda&#64;trobz.com">duyda&#64;trobz.com</a>&gt;</li>
<li>Ricardo Jara (Spearhead) &lt;<a class="reference external" href="mailto:rvjaraj&#64;gmail.com">rvjaraj&#64;gmail.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
Expand All @@ -439,6 +448,5 @@ <h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
</div>
</div>
</div>
</div>
</body>
</html>
63 changes: 63 additions & 0 deletions account_payment_line/tests/test_account_payment_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -931,3 +931,66 @@ def test_11_exceptions(self):
],
post=True,
)

def test_12_restrict_counterpart_partner(self):
# Without the restriction (default) the domain is empty and lines of
# a different partner can be added.
self.assertFalse(self.env.company.payment_line_restrict_counterpart_partner)
other_invoice = self._create_invoice("out_invoice", self.customer2, 100.0)
payment = self._create_payment(
self.customer,
100.0,
"inbound",
"customer",
[{"move_id": other_invoice}],
)
self.assertEqual(
payment.line_payment_counterpart_ids.counterpart_partner_domain, []
)
payment.line_payment_counterpart_ids.unlink()

# Enable the restriction at company level.
self.env.company.payment_line_restrict_counterpart_partner = True

own_invoice = self._create_invoice("out_invoice", self.customer, 100.0)
payment = self._create_payment(
self.customer,
100.0,
"inbound",
"customer",
[{"move_id": own_invoice}],
post=True,
)
self.assertEqual(
payment.line_payment_counterpart_ids.counterpart_partner_domain,
[("commercial_partner_id", "=", self.customer.commercial_partner_id.id)],
)
self.assertEqual(payment.state, "paid")

# Restriction enabled but no partner on the header yet: the selection
# is forbidden instead of falling back to every partner.
payment_without_partner = self.env["account.payment"].create(
{
"journal_id": self.bank_journal.id,
"payment_type": "inbound",
"partner_type": "customer",
"amount": 100.0,
}
)
self.assertFalse(payment_without_partner.partner_id)
line_without_partner = self.env["account.payment.counterpart.line"].new(
{"payment_id": payment_without_partner.id}
)
self.assertEqual(
line_without_partner.counterpart_partner_domain, [("id", "=", False)]
)

# Applying an invoice of a different partner must be forbidden.
with self.assertRaises(ValidationError):
self._create_payment(
self.customer,
100.0,
"inbound",
"customer",
[{"move_id": other_invoice}],
)
2 changes: 2 additions & 0 deletions account_payment_line/views/account_payment_views.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
<field name="arch" type="xml">
<list editable="top">
<field name="currency_id" column_invisible="1" />
<field name="counterpart_partner_domain" column_invisible="1" />
<field name="name" />
<field
name="partner_id"
optional="show"
options="{'no_create': True}"
domain="counterpart_partner_domain"
/>
<field name="account_id" options="{'no_create': True}" />
<field
Expand Down
Loading
Loading