Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e2c132f1b | |||
| 43b6ab10db | |||
| 9d0e51391c |
0
.gitignore
vendored
Normal file → Executable file
0
.gitignore
vendored
Normal file → Executable file
0
AMOUNT_FIX_GUIDE.md
Normal file → Executable file
0
AMOUNT_FIX_GUIDE.md
Normal file → Executable file
0
CHANGELOG.md
Normal file → Executable file
0
CHANGELOG.md
Normal file → Executable file
0
__init__.py
Normal file → Executable file
0
__init__.py
Normal file → Executable file
2
__manifest__.py
Normal file → Executable file
2
__manifest__.py
Normal file → Executable 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.
20
fix_amount_issue.py
Normal file → Executable file
20
fix_amount_issue.py
Normal file → Executable file
@ -24,23 +24,25 @@ def fix_payment_amounts():
|
|||||||
fixed_count = 0
|
fixed_count = 0
|
||||||
for payment in payments:
|
for payment in payments:
|
||||||
if payment.move_id:
|
if payment.move_id:
|
||||||
# Find the counterpart line (payable/expense line with debit)
|
# Robust logic to find gross amount from moves
|
||||||
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)
|
||||||
|
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)
|
||||||
current_amount = payment.amount
|
current_amount = payment.amount
|
||||||
|
|
||||||
# Check if amount needs fixing (allow for small rounding differences)
|
# Check if amount needs fixing (allow for small rounding differences)
|
||||||
if abs(current_amount - correct_amount) > 0.01:
|
if abs(current_amount - correct_amount) > 0.001:
|
||||||
print(f"Payment {payment.name} (ID: {payment.id}):")
|
print(f"Payment {payment.name} (ID: {payment.id}):")
|
||||||
print(f" Current amount: {current_amount}")
|
print(f" Current amount: {current_amount}")
|
||||||
print(f" Correct amount: {correct_amount}")
|
print(f" Correct amount: {correct_amount}")
|
||||||
print(f" Deductions: {payment.amount_substract}")
|
print(f" Deductions: {payment.amount_substract}")
|
||||||
print(f" Current final: {payment.final_payment_amount}")
|
|
||||||
print(f" Expected final: {correct_amount - payment.amount_substract}")
|
|
||||||
|
|
||||||
# Fix the amount using SQL to avoid triggering computed fields
|
# Fix the amount using SQL to avoid triggering computed fields
|
||||||
env.cr.execute(
|
env.cr.execute(
|
||||||
|
|||||||
0
models/__init__.py
Normal file → Executable file
0
models/__init__.py
Normal file → Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
0
models/account_batch_payment.py
Normal file → Executable file
0
models/account_batch_payment.py
Normal file → Executable file
77
models/account_payment.py
Normal file → Executable file
77
models/account_payment.py
Normal file → Executable file
@ -100,13 +100,18 @@ class AccountPayment(models.Model):
|
|||||||
if payment.amount_substract and payment.amount_substract > 0:
|
if payment.amount_substract and payment.amount_substract > 0:
|
||||||
# Get the correct amount from the journal entry
|
# Get the correct amount from the journal entry
|
||||||
if payment.move_id:
|
if payment.move_id:
|
||||||
# Find the counterpart line (payable/expense line)
|
liquidity_lines, counterpart_lines, writeoff_lines = payment._seek_for_lines()
|
||||||
counterpart_lines = payment.move_id.line_ids.filtered(
|
non_liquidity_lines = counterpart_lines + writeoff_lines
|
||||||
lambda l: l.account_id.account_type in ('liability_payable', 'expense') and l.debit > 0
|
|
||||||
)
|
# Find gross amount lines (Debits for outbound, Credits for inbound)
|
||||||
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: # Allow for rounding differences
|
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:
|
||||||
import logging
|
import logging
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
_logger.info(f"Fixing amount for payment {payment.id}: {payment.amount} -> {correct_amount}")
|
_logger.info(f"Fixing amount for payment {payment.id}: {payment.amount} -> {correct_amount}")
|
||||||
@ -133,14 +138,19 @@ class AccountPayment(models.Model):
|
|||||||
fixed_count = 0
|
fixed_count = 0
|
||||||
for payment in payments:
|
for payment in payments:
|
||||||
if payment.move_id:
|
if payment.move_id:
|
||||||
# Find the counterpart line (payable/expense line with debit)
|
# Robust logic to find gross amount from moves
|
||||||
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:
|
# Find gross amount lines (Debits for outbound, Credits for inbound)
|
||||||
correct_amount = counterpart_lines[0].debit
|
if payment.payment_type == 'outbound':
|
||||||
if abs(payment.amount - correct_amount) > 0.01:
|
gross_lines = non_liquidity_lines.filtered(lambda l: l.debit > 0)
|
||||||
|
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",
|
||||||
@ -165,36 +175,49 @@ class AccountPayment(models.Model):
|
|||||||
Override to handle synchronization when we have deductions.
|
Override to handle synchronization when we have deductions.
|
||||||
|
|
||||||
When we have a substract amount, the bank credit line is reduced to final_payment_amount,
|
When we have a substract amount, the bank credit line is reduced to final_payment_amount,
|
||||||
but we want to keep the payment amount at the original value (not sync it down).
|
but we want to keep the payment amount at the original gross value.
|
||||||
"""
|
"""
|
||||||
# For payments with deductions, we need to handle synchronization carefully
|
# For payments with deductions, we need to handle synchronization carefully
|
||||||
for payment in self:
|
for payment in self:
|
||||||
if payment.amount_substract and payment.amount_substract > 0:
|
if payment.amount_substract and payment.amount_substract > 0:
|
||||||
# Store the original amount before any synchronization
|
# Store potential original values
|
||||||
original_amount = payment.amount
|
original_amount = payment.amount
|
||||||
original_substract = payment.amount_substract
|
|
||||||
|
|
||||||
# Try to call parent sync but handle any errors
|
# Call parent sync
|
||||||
try:
|
try:
|
||||||
super(AccountPayment, payment)._synchronize_from_moves(changed_fields)
|
super(AccountPayment, payment)._synchronize_from_moves(changed_fields)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# If there's an error (like missing payable account when using expense_account_id),
|
|
||||||
# that's expected, so we just continue
|
|
||||||
import logging
|
import logging
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
_logger.info(f"Sync error for payment {payment.id} (expected with deductions): {e}")
|
_logger.debug(f"Sync info for payment {payment.id} (handling deductions): {e}")
|
||||||
|
|
||||||
# After sync, ensure the amount is still correct
|
# Restore gross amount from the move's counterpart lines
|
||||||
# The sync might have changed it based on journal entry lines
|
if payment.move_id:
|
||||||
if payment.amount != original_amount:
|
liquidity_lines, counterpart_lines, writeoff_lines = payment._seek_for_lines()
|
||||||
|
|
||||||
|
# The gross amount is the sum of counterpart/writeoff lines that balance the liquidity line
|
||||||
|
# For outbound (Send Money): Gross = Sum of Debits (excluding liquidity)
|
||||||
|
# For inbound (Receive Money): Gross = Sum of Credits (excluding liquidity)
|
||||||
|
|
||||||
|
non_liquidity_lines = counterpart_lines + writeoff_lines
|
||||||
|
if payment.payment_type == 'outbound':
|
||||||
|
gross_lines = non_liquidity_lines.filtered(lambda l: l.debit > 0)
|
||||||
|
else:
|
||||||
|
gross_lines = non_liquidity_lines.filtered(lambda l: l.credit > 0)
|
||||||
|
|
||||||
|
if gross_lines:
|
||||||
|
# Use amount_currency because it represents the amount in payment currency
|
||||||
|
correct_gross_amount = sum(abs(l.amount_currency) for l in gross_lines)
|
||||||
|
|
||||||
|
if abs(payment.amount - correct_gross_amount) > 0.001:
|
||||||
import logging
|
import logging
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
_logger.info(f"Restoring amount for payment {payment.id}: {payment.amount} -> {original_amount}")
|
_logger.info(f"Restoring gross amount for payment {payment.id}: {payment.amount} -> {correct_gross_amount}")
|
||||||
|
|
||||||
# Use SQL to restore the original amount without triggering more syncs
|
# Use SQL to restore to avoid triggering more syncs
|
||||||
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",
|
||||||
(original_amount, payment.id)
|
(correct_gross_amount, payment.id)
|
||||||
)
|
)
|
||||||
payment.invalidate_recordset(['amount'])
|
payment.invalidate_recordset(['amount'])
|
||||||
|
|
||||||
|
|||||||
2
models/payment_deduction_line.py
Normal file → Executable file
2
models/payment_deduction_line.py
Normal file → Executable 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(
|
||||||
|
|||||||
0
security/ir.model.access.csv
Normal file → Executable file
0
security/ir.model.access.csv
Normal file → Executable file
0
tests/__init__.py
Normal file → Executable file
0
tests/__init__.py
Normal file → Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
5
tests/test_account_payment.py
Normal file → Executable file
5
tests/test_account_payment.py
Normal file → Executable 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(
|
||||||
|
|||||||
3
tests/test_batch_payment_integration.py
Normal file → Executable file
3
tests/test_batch_payment_integration.py
Normal file → Executable 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"""
|
||||||
|
|
||||||
|
|||||||
12
views/account_batch_payment_views.xml
Normal file → Executable file
12
views/account_batch_payment_views.xml
Normal file → Executable 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>
|
||||||
|
|||||||
4
views/account_payment_views.xml
Normal file → Executable file
4
views/account_payment_views.xml
Normal file → Executable 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"
|
||||||
|
|||||||
0
wizard/__init__.py
Normal file → Executable file
0
wizard/__init__.py
Normal file → Executable file
33
wizard/payment_amount_fix_wizard.py
Normal file → Executable file
33
wizard/payment_amount_fix_wizard.py
Normal file → Executable 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",
|
||||||
|
|||||||
4
wizard/payment_amount_fix_wizard_views.xml
Normal file → Executable file
4
wizard/payment_amount_fix_wizard_views.xml
Normal file → Executable 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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user