Files
enterprise-addons/l10n_kh_reports/tests/test_wt003_generation.py
T

312 lines
18 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from freezegun import freeze_time
from odoo import Command
from odoo.addons.account_reports.tests.common import TestAccountReportsCommon
from odoo.tests import tagged
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestWT003Generation(TestAccountReportsCommon):
@classmethod
@TestAccountReportsCommon.setup_country('kh')
def setUpClass(cls):
super().setUpClass()
# Prepare a sample of taxes for the tests.
cls.ChartTemplate = cls.env['account.chart.template'].with_company(cls.company_data['company'])
wth_tax_xml_ids = [
'l10n_kh_tax_purchase_15_wht_s',
'l10n_kh_tax_purchase_15_wht_i',
'l10n_kh_tax_purchase_6_wht_fd',
'l10n_kh_tax_purchase_4_wht_sd',
'l10n_kh_tax_purchase_10_wht_rental_legal',
'l10n_kh_tax_purchase_10_wht_rental_physical',
'l10n_kh_tax_purchase_14_wht_nr_i',
'l10n_kh_tax_purchase_14_wht_nr_r',
'l10n_kh_tax_purchase_14_wht_nr_t',
'l10n_kh_tax_purchase_14_wht_nr_div',
'l10n_kh_tax_purchase_14_wht_nr_s',
'l10n_kh_tax_purchase_10_m',
]
cls.wth_tax_set = cls.env['account.tax'].union(*[cls.ChartTemplate.ref(tax_xml_id) for tax_xml_id in wth_tax_xml_ids])
cls.withholding_sequence = cls.env['ir.sequence'].create({
'implementation': 'no_gap',
'name': 'Withholding Sequence',
'padding': 4,
'number_increment': 1,
})
cls.wth_tax_set.withholding_sequence_id = cls.withholding_sequence
# VAT
cls.l10n_kh_tax_purchase_10_m = cls.ChartTemplate.ref('l10n_kh_tax_purchase_10_m')
cls.company_data['company'].withholding_tax_base_account_id = cls.env['account.account'].create({
'code': 'WITHB',
'name': 'Withholding Tax Base Account',
'reconcile': True,
'account_type': 'asset_current',
})
@freeze_time('2025-01-15')
def test_wth_on_payment_export(self):
""" Generate an amount of bills using wth tax on payment, pay them, then test the export. """
invoice_data = [
("in_invoice", self.partner_a, "2025-01-15", [(100 * i, tax)])
for i, tax in enumerate(self.wth_tax_set, start=1)
]
invoice_vals = []
for move_type, partner, invoice_date, lines_data in invoice_data:
invoice_vals.append({
'move_type': move_type,
'invoice_date': invoice_date,
'partner_id': partner.id,
'invoice_line_ids': [
Command.create({
'name': 'Test line',
'quantity': 1.0,
'price_unit': amount,
'tax_ids': tax,
}) for amount, tax in lines_data
],
})
invoices = self.env['account.move'].create(invoice_vals)
invoices.action_post()
for invoice in invoices:
wizard = self.env['account.payment.register']\
.with_context(active_model='account.move', active_ids=invoice.ids)\
.create({})
wizard._create_payments()
report = self.env.ref('l10n_kh.l10n_kh_wt003')
options = self._generate_options(report, '2025-01-01', '2025-01-31')
sls = self.env[report.custom_handler_model_name].export_wt_003(options)['file_content']
expected_row_values = {
# Headers
**self._get_header_row_vals(),
# Sales data
2: (1, '01/15/2025', 'BILL/2025/01/0011', 1, '', 'partner_a', '1100.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '154.00'),
3: (2, '01/15/2025', 'BILL/2025/01/0010', 1, '', 'partner_a', '1000.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '140.00', '0.00'),
4: (3, '01/15/2025', 'BILL/2025/01/0009', 1, '', 'partner_a', '900.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '126.00', '0.00', '0.00'),
5: (4, '01/15/2025', 'BILL/2025/01/0008', 1, '', 'partner_a', '800.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '112.00', '0.00', '0.00', '0.00'),
6: (5, '01/15/2025', 'BILL/2025/01/0007', 1, '', 'partner_a', '700.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '98.00', '0.00', '0.00', '0.00', '0.00'),
7: (6, '01/15/2025', 'BILL/2025/01/0006', 1, '', 'partner_a', '600.00', '0.00', '0.00', '0.00', '0.00', '0.00', '60.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
8: (7, '01/15/2025', 'BILL/2025/01/0005', 1, '', 'partner_a', '500.00', '0.00', '0.00', '0.00', '0.00', '50.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
9: (8, '01/15/2025', 'BILL/2025/01/0004', 1, '', 'partner_a', '400.00', '0.00', '0.00', '0.00', '16.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
10: (9, '01/15/2025', 'BILL/2025/01/0003', 1, '', 'partner_a', '300.00', '0.00', '0.00', '18.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
11: (10, '01/15/2025', 'BILL/2025/01/0002', 1, '', 'partner_a', '200.00', '0.00', '30.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
12: (11, '01/15/2025', 'BILL/2025/01/0001', 1, '', 'partner_a', '100.00', '15.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
}
self._test_xlsx_file(sls, expected_row_values)
@freeze_time('2025-01-15')
def test_wth_on_invoice_export(self):
""" Repeat the previous test, but set the withholding tax to be applied on invoice. """
invoice_data = [
("in_invoice", self.partner_a, "2025-01-15", [(100 * i, tax)])
for i, tax in enumerate(self.wth_tax_set, start=1)
]
self.wth_tax_set.is_withholding_tax_on_payment = False
invoice_vals = []
for move_type, partner, invoice_date, lines_data in invoice_data:
invoice_vals.append({
'move_type': move_type,
'invoice_date': invoice_date,
'partner_id': partner.id,
'invoice_line_ids': [
Command.create({
'name': 'Test line',
'quantity': 1.0,
'price_unit': amount,
'tax_ids': tax,
}) for amount, tax in lines_data
],
})
invoices = self.env['account.move'].create(invoice_vals)
invoices.action_post()
report = self.env.ref('l10n_kh.l10n_kh_wt003')
options = self._generate_options(report, '2025-01-01', '2025-01-31')
sls = self.env[report.custom_handler_model_name].export_wt_003(options)['file_content']
expected_row_values = {
# Headers
**self._get_header_row_vals(),
# Sales data
2: (1, '01/15/2025', 'BILL/2025/01/0011', 1, '', 'partner_a', '1100.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '154.00'),
3: (2, '01/15/2025', 'BILL/2025/01/0010', 1, '', 'partner_a', '1000.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '140.00', '0.00'),
4: (3, '01/15/2025', 'BILL/2025/01/0009', 1, '', 'partner_a', '900.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '126.00', '0.00', '0.00'),
5: (4, '01/15/2025', 'BILL/2025/01/0008', 1, '', 'partner_a', '800.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '112.00', '0.00', '0.00', '0.00'),
6: (5, '01/15/2025', 'BILL/2025/01/0007', 1, '', 'partner_a', '700.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '98.00', '0.00', '0.00', '0.00', '0.00'),
7: (6, '01/15/2025', 'BILL/2025/01/0006', 1, '', 'partner_a', '600.00', '0.00', '0.00', '0.00', '0.00', '0.00', '60.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
8: (7, '01/15/2025', 'BILL/2025/01/0005', 1, '', 'partner_a', '500.00', '0.00', '0.00', '0.00', '0.00', '50.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
9: (8, '01/15/2025', 'BILL/2025/01/0004', 1, '', 'partner_a', '400.00', '0.00', '0.00', '0.00', '16.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
10: (9, '01/15/2025', 'BILL/2025/01/0003', 1, '', 'partner_a', '300.00', '0.00', '0.00', '18.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
11: (10, '01/15/2025', 'BILL/2025/01/0002', 1, '', 'partner_a', '200.00', '0.00', '30.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
12: (11, '01/15/2025', 'BILL/2025/01/0001', 1, '', 'partner_a', '100.00', '15.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
}
self._test_xlsx_file(sls, expected_row_values)
@freeze_time('2025-01-15')
def test_partner_type_export(self):
""" Generate an amount of bills having partners of different fpos, pay them, then test the export. """
fpos_ntax = self.ChartTemplate.ref('l10n_kh_fiscal_position_non_taxable_person')
fpos_oc = self.ChartTemplate.ref('l10n_kh_fiscal_position_overseas_company')
partner_ntax = self.partner_a.copy()
partner_ntax.write({
'name': 'Partner NTAX',
'property_account_position_id': fpos_ntax.id,
})
partner_oc = self.partner_a.copy()
partner_oc.write({
'name': 'Partner OC',
'property_account_position_id': fpos_oc.id,
})
self.partner_a.vat = '987654312'
invoice_data = [
("in_invoice", self.partner_a, '2025-01-15', [(500, self.wth_tax_set[0])]),
("in_invoice", partner_ntax, '2025-01-15', [(500, self.wth_tax_set[0])]),
("in_invoice", partner_oc, '2025-01-15', [(500, self.wth_tax_set[0])]),
]
invoice_vals = []
for move_type, partner, invoice_date, lines_data in invoice_data:
invoice_vals.append({
'move_type': move_type,
'invoice_date': invoice_date,
'partner_id': partner.id,
'invoice_line_ids': [
Command.create({
'name': 'Test line',
'quantity': 1.0,
'price_unit': amount,
'tax_ids': tax,
}) for amount, tax in lines_data
],
})
invoices = self.env['account.move'].create(invoice_vals)
invoices.action_post()
for invoice in invoices:
wizard = self.env['account.payment.register']\
.with_context(active_model='account.move', active_ids=invoice.ids)\
.create({})
wizard._create_payments()
report = self.env.ref('l10n_kh.l10n_kh_wt003')
options = self._generate_options(report, '2025-01-01', '2025-01-31')
sls = self.env[report.custom_handler_model_name].export_wt_003(options)['file_content']
expected_row_values = {
# Headers
**self._get_header_row_vals(),
# Sales data
2: (1, '01/15/2025', 'BILL/2025/01/0003', 3, '', 'Partner OC', '500.00', '75.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
3: (2, '01/15/2025', 'BILL/2025/01/0002', 2, '', 'Partner NTAX', '500.00', '75.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
4: (3, '01/15/2025', 'BILL/2025/01/0001', 1, '987654312', 'partner_a', '500.00', '75.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
}
self._test_xlsx_file(sls, expected_row_values)
@freeze_time('2025-01-15')
def test_number_gap(self):
""" Generate an amount of bills with wth and vat, and validate the numbers. """
invoice_data = [
("in_invoice", self.partner_a, '2025-01-15', [(500, self.wth_tax_set[0])]),
("in_invoice", self.partner_a, '2025-01-15', [(400, self.wth_tax_set[0]), (250, self.l10n_kh_tax_purchase_10_m)]),
("in_invoice", self.partner_a, '2025-01-15', [(300, self.l10n_kh_tax_purchase_10_m)]), # Will be skipped
("in_invoice", self.partner_a, '2025-01-15', [(650, False), (800, self.l10n_kh_tax_purchase_10_m)]), # Will be skipped
("in_invoice", self.partner_a, '2025-01-15', [(700, self.wth_tax_set[0])]),
]
invoice_vals = []
for move_type, partner, invoice_date, lines_data in invoice_data:
invoice_vals.append({
'move_type': move_type,
'invoice_date': invoice_date,
'partner_id': partner.id,
'invoice_line_ids': [
Command.create({
'name': 'Test line',
'quantity': 1.0,
'price_unit': amount,
'tax_ids': tax,
}) for amount, tax in lines_data
],
})
invoices = self.env['account.move'].create(invoice_vals)
invoices.action_post()
for invoice in invoices:
wizard = self.env['account.payment.register']\
.with_context(active_model='account.move', active_ids=invoice.ids)\
.create({})
wizard._create_payments()
report = self.env.ref('l10n_kh.l10n_kh_wt003')
options = self._generate_options(report, '2025-01-01', '2025-01-31')
sls = self.env[report.custom_handler_model_name].export_wt_003(options)['file_content']
expected_row_values = {
# Headers
**self._get_header_row_vals(),
# Sales data
2: (1, '01/15/2025', 'BILL/2025/01/0005', 1, '', 'partner_a', '700.00', '105.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
3: (2, '01/15/2025', 'BILL/2025/01/0002', 1, '', 'partner_a', '400.00', '60.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
4: (3, '01/15/2025', 'BILL/2025/01/0001', 1, '', 'partner_a', '500.00', '75.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00', '0.00'),
}
self._test_xlsx_file(sls, expected_row_values)
def _get_header_row_vals(self):
""" return the header vals to be used in the tests. They are quite long, so this avoids repetition."""
first_header = (
"ល.រ\nNo.",
"កាលបរិច្ឆេទ\nDate",
"លេខវិក្កយបត្រ\nInvoice Number",
"អ្នកទទួលប្រាក់\nRecipient",
"",
"",
"ទឹកប្រាក់ត្រូវបើកមុនកាត់ទុក\nAmount",
"ពន្ធកាត់ទុកលើនិវាសជន\nWithholding Tax on Residents",
"",
"",
"",
"",
"",
"ពន្ធកាត់ទុកលើនិវាសជន\nWithholding Tax on Non-residents",
"",
"",
"",
"",
)
second_header = (
"",
"",
"",
"ប្រភេទ\nType",
"លេខសម្គាល់ការចុះបញ្ចីពន្ធដារ\nTIN/BIN/TID",
"ឈ្មោះ\nName",
"",
"ការបំពេញសេវានានា សួយសារចំពោះទ្រព្យ អរូបីភាគកម្មក្នុងធនធានរ៉ែ\nPerformance of Service and \nRoyalty for intangibles, \ninterests in minerals(15%)",
"ការបង់ការប្រាក់ឱ្យអ្នកជាប់ពន្ធ មិនមែនជាធនាគារ\nPayment of interest to \nnon-bank or saving \ninstitution taxpayers(15%)",
"ការបង់ការប្រាក់ឱ្យអ្នកជាប់ពន្ធ ដែលមានគណនីសន្សំមានកាលកំណត់\nPayment of interest to \ntaxpayers who have fixed \nterm deposit accounts(6%)",
"ការបង់ការប្រាក់ឱ្យអ្នកជាប់ពន្ធ ដែលមានគណនីសន្សំគ្មានកាលកំណត់\nPayment of interest to \ntaxpayers who have \nnon-fixed term saving(4%)",
"ការបង់ថ្លៃឈ្នួលចលនទ្រព្យ និង អចលនទ្រព្យ (នីតិបុគ្គល)\nPayment of rental/lease of \nmovable and immovable \nproperty - Legal Person(10%)",
"ការបង់ថ្លៃឈ្នួលចលនទ្រព្យ និង អចលនទ្រព្យ (រូបវន្តបុគ្គល)\nPayment of rental/lease of \nmovable and immovable \nproperty - Physical Person(10%)",
"ការបង់ការប្រាក់\nPayment of Interest(14%)",
"ការបង់សួយសារ ថ្លៃឈ្នួល ចំនូលផ្សេងៗទាក់ទិន និងការប្រើប្រាស់ទ្រព្យសម្បត្តិ\nPayment of royalty, \nrental/leasing, and \nincome related to \nthe use of property(14%)",
"ការទូទាត់ថ្លៃសេវាគ្រប់គ្រង និងសេវាបច្ចេកទេសនានា\nPayment of management \nfee and technical \nservices(14%)",
"ការបង់ភាគលាភ\nPayment of Dividend(14%)",
"សេវា\nService(14%)",
)
return {
0: first_header,
1: second_header,
}