1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/l10n_ec_edi/tests/test_withhold_wizard.py
2024-12-10 09:04:09 +07:00

362 lines
17 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from freezegun import freeze_time
from odoo import Command
from odoo.exceptions import ValidationError
from odoo.tests import tagged, Form
from .common import TestEcEdiCommon
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestEcEdiWithholdWizard(TestEcEdiCommon):
# ===== TEST METHODS =====
def test_out_withhold_basic_computes(self):
wizard, out_invoice = self.get_wizard_and_invoice()
self.assertFalse(wizard.withhold_line_ids) # out_withhold has no default withhold lines
self.env['l10n_ec.wizard.account.withhold.line'].create({
'invoice_id': out_invoice.id,
'wizard_id': wizard.id,
'tax_id': self._get_tax_by_xml_id('tax_sale_withhold_vat_10').ids[0],
})
# creating a withhold line yields the expected values
self.assertEqual(len(wizard.withhold_line_ids), 1)
withhold_line = wizard.withhold_line_ids[0]
self.assertEqual(withhold_line.taxsupport_code, False)
self.assertEqual(withhold_line.base, 48)
self.assertEqual(withhold_line.amount, 4.8)
def test_out_withhold_basic_checks(self):
wizard, out_invoice = self.get_wizard_and_invoice()
with self.assertRaises(ValidationError):
wizard.action_create_and_post_withhold() # empty withhold can't be posted
with self.assertRaises(ValidationError):
self.env['l10n_ec.wizard.account.withhold.line'].create({
'invoice_id': out_invoice.id,
'wizard_id': wizard.id,
'tax_id': self._get_tax_by_xml_id('tax_sale_withhold_vat_10').ids[0],
'amount': -10, # no negative amount in withhold lines
})
def test_purchase_invoice_withhold(self, custom_taxpayer=False):
"""Creates a purchase invoice and checks that when adding a withhold
- the suggested taxes match the product default taxes
- the tax supports are a subset of the invoice's tax supports
- the withhold is successfully posted
- it is not allowed to add another withhold
"""
# Create purchase invoice and withhold wizard
wizard, purchase_invoice = self.get_wizard_and_purchase_invoice()
# Validate if the withholding tax established in the product is in the field default line creation wizard
if not custom_taxpayer:
wizard_tax_ids = wizard.withhold_line_ids.mapped('tax_id')
product_invoice_tax_ids = purchase_invoice.invoice_line_ids.mapped('product_id.l10n_ec_withhold_tax_id')
self.assertTrue(all(p_tax.id in wizard_tax_ids.ids for p_tax in product_invoice_tax_ids))
# Validation: wizard's tax supports is subset of invoice's tax supports
wizard_tax_support = set(wizard.withhold_line_ids.mapped('taxsupport_code'))
invoice_tax_support = set(purchase_invoice._l10n_ec_get_inv_taxsupports_and_amounts().keys())
self.assertTrue(wizard_tax_support.issubset(invoice_tax_support))
with freeze_time(self.frozen_today):
withhold = wizard.action_create_and_post_withhold()
self.assertEqual(withhold.state, 'posted')
purchase_invoice._compute_l10n_ec_withhold_inv_fields()
with self.assertRaises(ValidationError, msg="Multiple invoices are only supported in customer withholds"):
with freeze_time(self.frozen_today):
wizard = self.env['l10n_ec.wizard.account.withhold'].with_context(active_ids=purchase_invoice.id, active_model='account.move').create({})
def test_multiple_purchase_invoice_withhold(self, custom_taxpayer=False):
"""
Test creation of single withholds from multiple bills is blocked
"""
purchase_invoices = self.env['account.move']
for partner in (self.partner_a, self.partner_b):
with freeze_time(self.frozen_today):
purchase_invoices |= self.get_invoice({
'move_type': 'in_invoice',
'partner_id': partner.id,
'journal_id': self.company_data['default_journal_purchase'].id,
'l10n_ec_sri_payment_id': self.env.ref('l10n_ec.P1').id,
'invoice_line_ids': self.get_custom_purchase_invoice_line_vals(),
})
purchase_invoices.action_post()
with self.assertRaises(ValidationError, msg="Multiple invoices are only supported in customer withholds"):
with freeze_time(self.frozen_today):
wizard = self.env['l10n_ec.wizard.account.withhold'].with_context(active_ids=purchase_invoices.ids, active_model='account.move').create({})
wizard.document_number = '001-001-000000001'
wizard.action_create_and_post_withhold()
def test_custom_taxpayer_type_partner_on_purchase_invoice(self):
"""Tests test_purchase_invoice_withhold with a custom taxpayer as a partner."""
self.set_custom_taxpayer_type_on_partner_a()
self.test_purchase_invoice_withhold(custom_taxpayer=True)
def test_withold_invoice_partially_paid(self):
"""
Tests that a withhold can be created on a partially paid invoice
"""
wizard, invoice = self.get_wizard_and_invoice({
'invoice_payment_term_id': self.env.ref('account.account_payment_term_advance_60days').id,
})
line_to_reco = invoice.line_ids.filtered(lambda l: l.display_type
and invoice.currency_id.is_zero(l.balance - invoice.amount_total * 0.3))
self.env['account.payment.register'].with_context(active_model='account.move', active_ids=invoice.ids).create({
'amount': line_to_reco.balance,
})._create_payments()
self.assertEqual(invoice.payment_state, 'partial')
wizard.withhold_line_ids.create({
'wizard_id': wizard.id,
'invoice_id': invoice.id,
'tax_id': self._get_tax_by_xml_id('tax_sale_withhold_vat_10').id,
})
with freeze_time(self.frozen_today):
withhold = wizard.action_create_and_post_withhold()
expected_withhold = self.env['account.move.line'].search([('l10n_ec_withhold_invoice_id', '=', invoice.id)]).mapped('move_id')
self.assertEqual(withhold, expected_withhold)
def test_out_withhold_with_two_invoices(self):
"""
Test that when creating a batch withold for two invoices,
the withhold lines are well reconciled with their respective
invoices.
"""
# Create two customer invoices
inv_1 = self.get_invoice({'move_type': 'out_invoice', 'partner_id': self.partner_a.id})
inv_2 = self.get_invoice({'move_type': 'out_invoice', 'partner_id': self.partner_a.id, 'l10n_latam_document_number': '001-001-000000002'})
(inv_1 + inv_2).action_post()
# Create the withhold wizard with three withhold lines, to be sure that each line is reconciled with the right invoice
wizard = self.env['l10n_ec.wizard.account.withhold'].with_context(active_ids=(inv_1 + inv_2).ids, active_model='account.move').create({
'withhold_line_ids': [
Command.create({
'invoice_id': inv_1.id,
'tax_id': self._get_tax_by_xml_id('tax_sale_withhold_vat_10').id,
}),
Command.create({
'invoice_id': inv_1.id,
'tax_id': self._get_tax_by_xml_id('tax_withhold_profit_sale_1x100').id,
}),
Command.create({
'invoice_id': inv_2.id,
'tax_id': self._get_tax_by_xml_id('tax_sale_withhold_vat_10').id,
})
]
})
with freeze_time(self.frozen_today):
withhold = wizard.action_create_and_post_withhold()
# The two invoices lines should be reconciled with the withhold
for invoice in (inv_1, inv_2):
with self.subTest(invoice=invoice):
self.assertEqual(invoice.line_ids.filtered(lambda l: l.display_type == 'payment_term').matched_credit_ids.credit_move_id.move_id, withhold)
def test_computed_base_of_withhold_lines_1(self):
"""Test that the base amount of the withhold lines is still correct after triggering its computed method."""
invoice = self.env['account.move'].create({
'move_type': 'in_invoice',
'partner_id': self.partner_a.id,
'name': 'BILL/01',
'invoice_date': self.frozen_today,
'date': self.frozen_today,
'l10n_ec_sri_payment_id': self.env['l10n_ec.sri.payment'].search([('code', '=', 20)], limit=1).id, # Otros con utilización del sistema financiero (see l10n_ec.sri.payment.csv)
'l10n_latam_document_number': '001-001-000000001',
'invoice_line_ids': [
Command.create({
'product_id': self.product_a.id,
'quantity': 1,
'price_unit': 100,
'tax_ids': [Command.set(self._get_tax_by_xml_id('tax_vat_510_sup_01').ids)],
}),
Command.create({
'name': 'No product line',
'quantity': 1,
'price_unit': 50,
'tax_ids': [Command.set(self._get_tax_by_xml_id('tax_vat_510_sup_01').ids)],
}),
],
})
invoice.action_post()
wizard = self.env['l10n_ec.wizard.account.withhold'].with_context(active_ids=invoice.id, active_model='account.move').new({})
default_base = wizard.withhold_line_ids.mapped('base')
wizard.withhold_line_ids._compute_base()
computed_base = wizard.withhold_line_ids.mapped('base')
self.assertEqual(computed_base, default_base)
def test_computed_base_of_withhold_lines_2(self):
"""Test that the base amount of withholding lines correctly assigned"""
self.set_custom_taxpayer_type_on_partner_a()
l10n_ec_sri_payment_id = self.env['l10n_ec.sri.payment'].search([('code', '=', 20)], limit=1)
tax_vat_510_sup_01_id = self._get_tax_by_xml_id('tax_vat_510_sup_01')
tax_vat_510_sup_05_id = self._get_tax_by_xml_id('tax_vat_510_sup_05')
tax_withhold_vat_20 = self._get_tax_by_xml_id('tax_withhold_vat_20')
bill_1 = self.env['account.move'].create({
'move_type': 'in_invoice',
'partner_id': self.partner_a.id,
'name': 'BILL/01',
'invoice_date': self.frozen_today,
'date': self.frozen_today,
'l10n_ec_sri_payment_id': l10n_ec_sri_payment_id.id,
'l10n_latam_document_number': '001-001-000000001',
'invoice_line_ids': [
Command.create({
'product_id': self.product_a.id,
'quantity': 1,
'price_unit': 100,
'tax_ids': [Command.set(tax_vat_510_sup_01_id.ids)],
}),
],
})
bill_1.action_post()
Wizard = self.env['l10n_ec.wizard.account.withhold'].with_context(active_ids=bill_1.id, active_model='account.move')
wizard_form = Form(Wizard)
wizard_form.document_number = '001-001-000000001'
# Initial Wizard data
# Tax Support | Tax | Base | Amount |
# 01 | 10% 303 | 100.0 | 10.0 |
# 01 | 10% WH | 12.0 | 1.2 |
with wizard_form.withhold_line_ids.edit(0) as wizard_line_form:
self.assertEqual(wizard_line_form.base, 100.0, 'base should be the subtotal from bill line')
self.assertEqual(wizard_line_form.amount, 10.0, 'amount should be the tax amount from bill line')
# Edit WH tax amount
# Tax Support | Tax | Base | Amount |
# 01 | 10% 303 | 100.0 | 10.0 |
# 01 | 10% WH | 10.0 | 1.0 |
with wizard_form.withhold_line_ids.edit(1) as wizard_line_form:
self.assertEqual(wizard_line_form.base, 12.0, 'base should be calculated on tax amount')
self.assertEqual(wizard_line_form.amount, 1.2)
wizard_line_form.base = 10.0
# Add another line with no available remaining amount
# Tax Support | Tax | Base | Amount |
# 01 | 10% 303 | 100.0 | 10.0 |
# 01 | 10% WH | 10.0 | 1.0 |
# 01 | 10% 303 | 0.0 | 0.0 |
with wizard_form.withhold_line_ids.new() as wizard_line_form:
wizard_line_form.taxsupport_code = '01'
wizard_line_form.tax_id = bill_1.commercial_partner_id.l10n_ec_taxpayer_type_id.profit_withhold_tax_id
self.assertEqual(wizard_line_form.base, 0.0, 'base should be 0')
# Change last line tax to 20%, remaining base should recompute accordingly
# Tax Support | Tax | Base | Amount |
# 01 | 10% 303 | 100.0 | 10.0 |
# 01 | 10% WH | 10.0 | 1.0 |
# 01 | 20% WH | 2.0 | 0.4 |
with wizard_form.withhold_line_ids.edit(2) as wizard_line_form:
wizard_line_form.tax_id = tax_withhold_vat_20
self.assertEqual(wizard_line_form.base, 2.0, 'base should be the remaining amount (2.0)')
# Add another tax line 20%, with no remaining base amounts should be 0
# Tax Support | Tax | Base | Amount |
# 01 | 10% 303 | 100.0 | 10.0 |
# 01 | 10% WH | 10.0 | 1.0 |
# 01 | 20% WH | 2.0 | 0.4 |
# 01 | 20% WH | 0.0 | 0.0 |
with wizard_form.withhold_line_ids.new() as wizard_line_form:
wizard_line_form.taxsupport_code = '01'
wizard_line_form.tax_id = tax_withhold_vat_20
self.assertEqual(wizard_line_form.base, 0.0, 'base should be 0')
# Remove last line before saving
wizard_form.withhold_line_ids.remove(3)
wizard = wizard_form.save()
expected_values = [{
'taxsupport_code': '01',
'tax_id': bill_1.commercial_partner_id.l10n_ec_taxpayer_type_id.profit_withhold_tax_id.id,
'base': 100.0,
'amount': 10.0,
}, {
'taxsupport_code': '01',
'tax_id': bill_1.commercial_partner_id.l10n_ec_taxpayer_type_id.vat_goods_withhold_tax_id.id,
'base': 10.0,
'amount': 1.0,
}, {
'taxsupport_code': '01',
'tax_id': tax_withhold_vat_20.id,
'base': 2.0,
'amount': 0.4,
}]
self.assertRecordValues(wizard.withhold_line_ids, expected_values)
bill_2 = self.env['account.move'].create({
'move_type': 'in_invoice',
'partner_id': self.partner_a.id,
'name': 'BILL/01',
'invoice_date': self.frozen_today,
'date': self.frozen_today,
'l10n_ec_sri_payment_id': l10n_ec_sri_payment_id.id,
'l10n_latam_document_number': '001-001-000000002',
'invoice_line_ids': [
Command.create({
'product_id': self.product_a.id,
'quantity': 1,
'price_unit': 100,
'tax_ids': [Command.set(tax_vat_510_sup_01_id.ids)],
}),
Command.create({
'product_id': self.product_a.id,
'quantity': 1,
'price_unit': 10,
'tax_ids': [Command.set(tax_vat_510_sup_05_id.ids)],
}),
],
})
bill_2.action_post()
wizard = self.env['l10n_ec.wizard.account.withhold'].with_context(active_ids=bill_2.id, active_model='account.move').create({})
expected_values = [{
'taxsupport_code': '01',
'tax_id': bill_2.commercial_partner_id.l10n_ec_taxpayer_type_id.profit_withhold_tax_id.id,
'base': 100.0,
'amount': 10.0,
}, {
'taxsupport_code': '05',
'tax_id': bill_2.commercial_partner_id.l10n_ec_taxpayer_type_id.profit_withhold_tax_id.id,
'base': 10.0,
'amount': 1.0,
}, {
'taxsupport_code': '01',
'tax_id': bill_2.commercial_partner_id.l10n_ec_taxpayer_type_id.vat_goods_withhold_tax_id.id,
'base': 12.0,
'amount': 1.2,
}, {
'taxsupport_code': '05',
'tax_id': bill_2.commercial_partner_id.l10n_ec_taxpayer_type_id.vat_goods_withhold_tax_id.id,
'base': 1.2,
'amount': 0.12,
}]
self.assertRecordValues(wizard.withhold_line_ids, expected_values)
# ===== HELPER METHODS =====
def get_wizard_and_invoice(self, invoice_args=None):
invoice_vals = {
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
}
if invoice_args:
invoice_vals.update(invoice_args)
invoice = self.get_invoice(invoice_vals)
invoice.action_post()
wizard = self.env['l10n_ec.wizard.account.withhold'].with_context(active_ids=invoice.id, active_model='account.move')
return wizard.create({}), invoice