Compare commits

..

3 Commits
main ... 19.0

15 changed files with 38 additions and 27 deletions

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
{ {
'name': 'Vendor Payment Diff Amount', 'name': 'Vendor Payment Diff Amount',
'version': '17.0.2.1.0', 'version': '19.0.2.1.0',
'category': 'Accounting/Accounting', 'category': 'Accounting/Accounting',
'summary': 'Support multiple payment deductions for vendor payments (withholding tax, fees, etc.)', 'summary': 'Support multiple payment deductions for vendor payments (withholding tax, fees, etc.)',
'description': """ 'description': """

Binary file not shown.

View File

@ -58,7 +58,7 @@ class PaymentDeductionLine(models.Model):
'account.account', 'account.account',
string='Deduction Account', string='Deduction Account',
required=True, required=True,
domain="[('account_type', 'not in', ['asset_cash', 'asset_cash_bank', 'asset_receivable', 'liability_payable']), ('deprecated', '=', False)]", domain="[('account_type', 'not in', ['asset_cash', 'asset_cash_bank', 'asset_receivable', 'liability_payable']), ('active', '=', True)]",
help='Account where the deduction will be recorded (use tax payable or expense accounts, NOT payable/receivable accounts)', help='Account where the deduction will be recorded (use tax payable or expense accounts, NOT payable/receivable accounts)',
) )
name = fields.Char( name = fields.Char(

View File

@ -1,11 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from odoo import fields from odoo import fields
from odoo.tests import TransactionCase from odoo.tests import TransactionCase, tagged
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from hypothesis import given, strategies as st, settings from hypothesis import given, strategies as st, settings
@tagged('post_install', '-at_install')
class TestAccountPayment(TransactionCase): class TestAccountPayment(TransactionCase):
"""Test cases for vendor payment deduction functionality""" """Test cases for vendor payment deduction functionality"""
@ -37,7 +38,7 @@ class TestAccountPayment(TransactionCase):
'name': 'Withholding Tax Account', 'name': 'Withholding Tax Account',
'code': 'WHT001', 'code': 'WHT001',
'account_type': 'expense', 'account_type': 'expense',
'company_id': self.env.company.id, 'company_ids': [self.env.company.id],
}) })
@given( @given(

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from odoo import fields from odoo import fields
from odoo.tests import TransactionCase from odoo.tests import TransactionCase, tagged
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
@tagged('post_install', '-at_install')
class TestBatchPaymentIntegration(TransactionCase): class TestBatchPaymentIntegration(TransactionCase):
"""Test cases for batch payment integration with deduction functionality""" """Test cases for batch payment integration with deduction functionality"""

View File

@ -1,15 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<!-- Add deduction lines field to batch payment line tree view --> <!-- Add deduction lines field to batch payment line list view -->
<record id="view_batch_payment_form_inherit_diff_amount" model="ir.ui.view"> <record id="view_batch_payment_form_inherit_diff_amount" model="ir.ui.view">
<field name="name">account.batch.payment.form.inherit.diff.amount</field> <field name="name">account.batch.payment.form.inherit.diff.amount</field>
<field name="model">account.batch.payment</field> <field name="model">account.batch.payment</field>
<field name="inherit_id" ref="vendor_batch_payment_merge.view_batch_payment_form_inherit"/> <field name="inherit_id" ref="vendor_batch_payment_merge.view_batch_payment_form_inherit"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<!-- Replace the tree view with one that includes a form view for deduction lines --> <!-- Replace the list view with one that includes a form view for deduction lines -->
<xpath expr="//field[@name='direct_payment_line_ids']" position="replace"> <xpath expr="//field[@name='direct_payment_line_ids']" position="replace">
<field name="direct_payment_line_ids"> <field name="direct_payment_line_ids">
<tree editable="bottom"> <list editable="bottom">
<field name="partner_id" domain="parent.batch_type == 'outbound' and [('supplier_rank', '>', 0)] or [('customer_rank', '>', 0)]" options="{'no_create': True}"/> <field name="partner_id" domain="parent.batch_type == 'outbound' and [('supplier_rank', '>', 0)] or [('customer_rank', '>', 0)]" options="{'no_create': True}"/>
<field name="amount" sum="Total"/> <field name="amount" sum="Total"/>
<field name="expense_account_id"/> <field name="expense_account_id"/>
@ -17,7 +17,7 @@
<field name="memo"/> <field name="memo"/>
<field name="date"/> <field name="date"/>
<field name="payment_id" readonly="1"/> <field name="payment_id" readonly="1"/>
</tree> </list>
<form> <form>
<group> <group>
<group name="payment_info"> <group name="payment_info">
@ -32,13 +32,13 @@
</group> </group>
<group string="Deductions" name="deductions"> <group string="Deductions" name="deductions">
<field name="deduction_line_ids" nolabel="1" context="{'default_currency_id': currency_id}"> <field name="deduction_line_ids" nolabel="1" context="{'default_currency_id': currency_id}">
<tree editable="bottom"> <list editable="bottom">
<field name="sequence" widget="handle"/> <field name="sequence" widget="handle"/>
<field name="substract_account_id" required="1"/> <field name="substract_account_id" required="1"/>
<field name="name" placeholder="Description (optional)"/> <field name="name" placeholder="Description (optional)"/>
<field name="amount_substract" required="1" sum="Total"/> <field name="amount_substract" required="1" sum="Total"/>
<field name="currency_id" column_invisible="1"/> <field name="currency_id" column_invisible="1"/>
</tree> </list>
</field> </field>
<field name="amount_substract" readonly="1"/> <field name="amount_substract" readonly="1"/>
</group> </group>

View File

@ -12,14 +12,14 @@
invisible="payment_type != 'outbound'" invisible="payment_type != 'outbound'"
readonly="state != 'draft'" readonly="state != 'draft'"
nolabel="1"> nolabel="1">
<tree editable="bottom"> <list editable="bottom">
<field name="sequence" widget="handle"/> <field name="sequence" widget="handle"/>
<field name="substract_account_id" required="1"/> <field name="substract_account_id" required="1"/>
<field name="name" placeholder="Description (optional)"/> <field name="name" placeholder="Description (optional)"/>
<field name="amount_substract" required="1" sum="Total Deductions"/> <field name="amount_substract" required="1" sum="Total Deductions"/>
<field name="currency_id" column_invisible="1"/> <field name="currency_id" column_invisible="1"/>
<field name="company_id" column_invisible="1"/> <field name="company_id" column_invisible="1"/>
</tree> </list>
</field> </field>
<label for="amount_substract" string="Total Deductions" <label for="amount_substract" string="Total Deductions"

View File

@ -28,12 +28,17 @@ class PaymentAmountFixWizard(models.TransientModel):
payments_to_fix = [] payments_to_fix = []
for payment in payments: for payment in payments:
if payment.move_id: if payment.move_id:
counterpart_lines = payment.move_id.line_ids.filtered( liquidity_lines, counterpart_lines, writeoff_lines = payment._seek_for_lines()
lambda l: l.debit > 0 and l.account_id.account_type in ('liability_payable', 'expense') non_liquidity_lines = counterpart_lines + writeoff_lines
)
if counterpart_lines: if payment.payment_type == 'outbound':
correct_amount = counterpart_lines[0].debit gross_lines = non_liquidity_lines.filtered(lambda l: l.debit > 0)
if abs(payment.amount - correct_amount) > 0.01: else:
gross_lines = non_liquidity_lines.filtered(lambda l: l.credit > 0)
if gross_lines:
correct_amount = sum(abs(l.amount_currency) for l in gross_lines)
if abs(payment.amount - correct_amount) > 0.001:
payments_to_fix.append(payment.id) payments_to_fix.append(payment.id)
res['payment_ids'] = [(6, 0, payments_to_fix)] res['payment_ids'] = [(6, 0, payments_to_fix)]
@ -45,13 +50,17 @@ class PaymentAmountFixWizard(models.TransientModel):
for payment in self.payment_ids: for payment in self.payment_ids:
if payment.move_id: if payment.move_id:
counterpart_lines = payment.move_id.line_ids.filtered( liquidity_lines, counterpart_lines, writeoff_lines = payment._seek_for_lines()
lambda l: l.debit > 0 and l.account_id.account_type in ('liability_payable', 'expense') non_liquidity_lines = counterpart_lines + writeoff_lines
)
if counterpart_lines: if payment.payment_type == 'outbound':
correct_amount = counterpart_lines[0].debit gross_lines = non_liquidity_lines.filtered(lambda l: l.debit > 0)
if abs(payment.amount - correct_amount) > 0.01: else:
gross_lines = non_liquidity_lines.filtered(lambda l: l.credit > 0)
if gross_lines:
correct_amount = sum(abs(l.amount_currency) for l in gross_lines)
if abs(payment.amount - correct_amount) > 0.001:
# Fix using SQL to avoid sync issues # Fix using SQL to avoid sync issues
payment.env.cr.execute( payment.env.cr.execute(
"UPDATE account_payment SET amount = %s WHERE id = %s", "UPDATE account_payment SET amount = %s WHERE id = %s",

View File

@ -12,14 +12,14 @@
</p> </p>
<group> <group>
<field name="payment_ids" nolabel="1"> <field name="payment_ids" nolabel="1">
<tree> <list>
<field name="name"/> <field name="name"/>
<field name="partner_id"/> <field name="partner_id"/>
<field name="amount"/> <field name="amount"/>
<field name="amount_substract"/> <field name="amount_substract"/>
<field name="final_payment_amount"/> <field name="final_payment_amount"/>
<field name="date"/> <field name="date"/>
</tree> </list>
</field> </field>
</group> </group>
<footer> <footer>