vendor_payment_diff_amount/tests/test_batch_payment_integration.py

336 lines
15 KiB
Python

# -*- coding: utf-8 -*-
from odoo import fields
from odoo.tests import TransactionCase
from odoo.exceptions import ValidationError
class TestBatchPaymentIntegration(TransactionCase):
"""Test cases for batch payment integration with deduction functionality"""
def setUp(self):
super(TestBatchPaymentIntegration, self).setUp()
# Create test partners (suppliers)
self.partner1 = self.env['res.partner'].create({
'name': 'Test Vendor 1',
'supplier_rank': 1,
})
self.partner2 = self.env['res.partner'].create({
'name': 'Test Vendor 2',
'supplier_rank': 1,
})
# Get or create bank journal
self.journal = self.env['account.journal'].search([
('type', '=', 'bank'),
('company_id', '=', self.env.company.id)
], limit=1)
if not self.journal:
self.journal = self.env['account.journal'].create({
'name': 'Test Bank',
'type': 'bank',
'code': 'TBNK',
'company_id': self.env.company.id,
})
# Create substract account (expense account)
self.substract_account = self.env['account.account'].create({
'name': 'Withholding Tax Account',
'code': 'WHT001',
'account_type': 'expense',
'company_id': self.env.company.id,
})
# Create expense account for batch payment lines
self.expense_account = self.env['account.account'].create({
'name': 'General Expense Account',
'code': 'EXP001',
'account_type': 'expense',
'company_id': self.env.company.id,
})
def test_property_batch_payment_line_field_transfer(self):
"""
**Feature: vendor-payment-diff-amount, Property 13: Batch payment line field transfer**
**Validates: Requirements 7.4, 7.5**
Property: For any batch payment line with amount_substract and substract_account_id
values, when payments are generated, the created payment should have the same
amount_substract and substract_account_id values.
"""
# Create batch payment
batch_payment = self.env['account.batch.payment'].create({
'journal_id': self.journal.id,
'batch_type': 'outbound',
'date': fields.Date.today(),
})
# Create direct payment lines with deduction fields
line1 = self.env['account.batch.payment.line'].create({
'batch_payment_id': batch_payment.id,
'partner_id': self.partner1.id,
'amount': 1000.0,
'amount_substract': 100.0,
'substract_account_id': self.substract_account.id,
'expense_account_id': self.expense_account.id,
'memo': 'Payment 1 with deduction',
'date': fields.Date.today(),
})
line2 = self.env['account.batch.payment.line'].create({
'batch_payment_id': batch_payment.id,
'partner_id': self.partner2.id,
'amount': 2000.0,
'amount_substract': 200.0,
'substract_account_id': self.substract_account.id,
'expense_account_id': self.expense_account.id,
'memo': 'Payment 2 with deduction',
'date': fields.Date.today(),
})
# Verify lines were created with correct values
self.assertEqual(line1.amount_substract, 100.0,
"Line 1 should have amount_substract of 100")
self.assertEqual(line1.substract_account_id, self.substract_account,
"Line 1 should have correct substract_account_id")
self.assertEqual(line2.amount_substract, 200.0,
"Line 2 should have amount_substract of 200")
self.assertEqual(line2.substract_account_id, self.substract_account,
"Line 2 should have correct substract_account_id")
# Generate payments from lines
batch_payment.generate_payments_from_lines()
# Verify payments were generated
self.assertTrue(line1.payment_id, "Payment should be generated for line 1")
self.assertTrue(line2.payment_id, "Payment should be generated for line 2")
# Get the generated payments
payment1 = line1.payment_id
payment2 = line2.payment_id
# Verify payment 1 has correct deduction fields transferred
self.assertEqual(payment1.amount, 1000.0,
"Payment 1 should have amount of 1000")
self.assertEqual(payment1.amount_substract, 100.0,
"Payment 1 should have amount_substract of 100 (transferred from line)")
self.assertEqual(payment1.substract_account_id, self.substract_account,
"Payment 1 should have correct substract_account_id (transferred from line)")
self.assertEqual(payment1.final_payment_amount, 900.0,
"Payment 1 final_payment_amount should be 900 (1000 - 100)")
# Verify payment 2 has correct deduction fields transferred
self.assertEqual(payment2.amount, 2000.0,
"Payment 2 should have amount of 2000")
self.assertEqual(payment2.amount_substract, 200.0,
"Payment 2 should have amount_substract of 200 (transferred from line)")
self.assertEqual(payment2.substract_account_id, self.substract_account,
"Payment 2 should have correct substract_account_id (transferred from line)")
self.assertEqual(payment2.final_payment_amount, 1800.0,
"Payment 2 final_payment_amount should be 1800 (2000 - 200)")
# Verify payments are posted
self.assertEqual(payment1.state, 'posted', "Payment 1 should be posted")
self.assertEqual(payment2.state, 'posted', "Payment 2 should be posted")
# Verify journal entries have correct structure with deduction lines
move1 = payment1.move_id
move2 = payment2.move_id
self.assertTrue(move1, "Payment 1 should have journal entry")
self.assertTrue(move2, "Payment 2 should have journal entry")
# Verify payment 1 journal entry has substract line
substract_lines1 = move1.line_ids.filtered(
lambda l: l.account_id == self.substract_account
)
self.assertGreater(len(substract_lines1), 0,
"Payment 1 journal entry should have substract account line")
# Verify payment 2 journal entry has substract line
substract_lines2 = move2.line_ids.filtered(
lambda l: l.account_id == self.substract_account
)
self.assertGreater(len(substract_lines2), 0,
"Payment 2 journal entry should have substract account line")
# Verify bank lines have correct amounts (original amount)
bank_account = payment1.outstanding_account_id
bank_line1 = move1.line_ids.filtered(lambda l: l.account_id == bank_account)
bank_line2 = move2.line_ids.filtered(lambda l: l.account_id == bank_account)
self.assertAlmostEqual(sum(bank_line1.mapped('credit')), 1000.0, places=2,
msg="Payment 1 bank credit should be 1000 (original amount)")
self.assertAlmostEqual(sum(bank_line2.mapped('credit')), 2000.0, places=2,
msg="Payment 2 bank credit should be 2000 (original amount)")
def test_unit_batch_payment_line_fields_exist(self):
"""
Unit test: Verify batch payment line model has deduction fields.
Tests Requirements 7.1, 7.2, 7.3
"""
# Create batch payment
batch_payment = self.env['account.batch.payment'].create({
'journal_id': self.journal.id,
'batch_type': 'outbound',
'date': fields.Date.today(),
})
# Create batch payment line
line = self.env['account.batch.payment.line'].create({
'batch_payment_id': batch_payment.id,
'partner_id': self.partner1.id,
'amount': 1000.0,
'date': fields.Date.today(),
})
# Verify fields exist
self.assertTrue(hasattr(line, 'amount_substract'),
"Batch payment line should have amount_substract field")
self.assertTrue(hasattr(line, 'substract_account_id'),
"Batch payment line should have substract_account_id field")
# Verify fields can be set
line.write({
'amount_substract': 100.0,
'substract_account_id': self.substract_account.id,
})
self.assertEqual(line.amount_substract, 100.0,
"amount_substract should be settable")
self.assertEqual(line.substract_account_id, self.substract_account,
"substract_account_id should be settable")
def test_unit_batch_payment_without_deduction(self):
"""
Unit test: Verify batch payment works without deduction fields.
Tests that the integration doesn't break existing functionality.
"""
# Create batch payment
batch_payment = self.env['account.batch.payment'].create({
'journal_id': self.journal.id,
'batch_type': 'outbound',
'date': fields.Date.today(),
})
# Create direct payment line WITHOUT deduction fields
line = self.env['account.batch.payment.line'].create({
'batch_payment_id': batch_payment.id,
'partner_id': self.partner1.id,
'amount': 1000.0,
'expense_account_id': self.expense_account.id,
'memo': 'Payment without deduction',
'date': fields.Date.today(),
})
# Verify line was created without deduction fields
self.assertEqual(line.amount_substract, 0.0,
"amount_substract should default to 0")
self.assertFalse(line.substract_account_id,
"substract_account_id should be False by default")
# Generate payments from lines
batch_payment.generate_payments_from_lines()
# Verify payment was generated
self.assertTrue(line.payment_id, "Payment should be generated")
# Get the generated payment
payment = line.payment_id
# Verify payment has no deduction
self.assertEqual(payment.amount, 1000.0,
"Payment should have amount of 1000")
self.assertEqual(payment.amount_substract, 0.0,
"Payment should have amount_substract of 0")
self.assertFalse(payment.substract_account_id,
"Payment should not have substract_account_id")
self.assertEqual(payment.final_payment_amount, 1000.0,
"Payment final_payment_amount should equal amount")
# Verify payment is posted
self.assertEqual(payment.state, 'posted', "Payment should be posted")
# Verify journal entry has standard structure (no substract line)
move = payment.move_id
self.assertTrue(move, "Payment should have journal entry")
# Verify no substract line
substract_lines = move.line_ids.filtered(
lambda l: l.account_id == self.substract_account
)
self.assertEqual(len(substract_lines), 0,
"Journal entry should not have substract account line")
def test_unit_batch_payment_mixed_lines(self):
"""
Unit test: Verify batch payment with mixed lines (some with deduction, some without).
Tests Requirements 7.4, 7.5
"""
# Create batch payment
batch_payment = self.env['account.batch.payment'].create({
'journal_id': self.journal.id,
'batch_type': 'outbound',
'date': fields.Date.today(),
})
# Create line WITH deduction
line_with_deduction = self.env['account.batch.payment.line'].create({
'batch_payment_id': batch_payment.id,
'partner_id': self.partner1.id,
'amount': 1000.0,
'amount_substract': 100.0,
'substract_account_id': self.substract_account.id,
'expense_account_id': self.expense_account.id,
'memo': 'With deduction',
'date': fields.Date.today(),
})
# Create line WITHOUT deduction
line_without_deduction = self.env['account.batch.payment.line'].create({
'batch_payment_id': batch_payment.id,
'partner_id': self.partner2.id,
'amount': 2000.0,
'expense_account_id': self.expense_account.id,
'memo': 'Without deduction',
'date': fields.Date.today(),
})
# Generate payments from lines
batch_payment.generate_payments_from_lines()
# Verify both payments were generated
self.assertTrue(line_with_deduction.payment_id,
"Payment should be generated for line with deduction")
self.assertTrue(line_without_deduction.payment_id,
"Payment should be generated for line without deduction")
# Get the generated payments
payment_with = line_with_deduction.payment_id
payment_without = line_without_deduction.payment_id
# Verify payment with deduction
self.assertEqual(payment_with.amount_substract, 100.0,
"Payment with deduction should have amount_substract")
self.assertEqual(payment_with.substract_account_id, self.substract_account,
"Payment with deduction should have substract_account_id")
self.assertEqual(payment_with.final_payment_amount, 900.0,
"Payment with deduction final amount should be 900")
# Verify payment without deduction
self.assertEqual(payment_without.amount_substract, 0.0,
"Payment without deduction should have amount_substract of 0")
self.assertFalse(payment_without.substract_account_id,
"Payment without deduction should not have substract_account_id")
self.assertEqual(payment_without.final_payment_amount, 2000.0,
"Payment without deduction final amount should equal amount")
# Verify both payments are posted
self.assertEqual(payment_with.state, 'posted',
"Payment with deduction should be posted")
self.assertEqual(payment_without.state, 'posted',
"Payment without deduction should be posted")