from odoo import Command from odoo.addons.l10n_in.tests.common import L10nInTestInvoicingCommon from odoo.tests import tagged @tagged('post_install_l10n', 'post_install', '-at_install') class TestTdsTcsAlert(L10nInTestInvoicingCommon): @classmethod def setUpClass(cls): super().setUpClass() ChartTemplate = cls.env['account.chart.template'] # ==== Chart of Accounts ==== cls.purchase_account = ChartTemplate.ref('p2107') cls.purchase_account.write({ 'l10n_in_tds_tcs_section_id': cls.env.ref('l10n_in_withholding.tds_section_194c').id }) cls.house_expense_account = ChartTemplate.ref('p2103') cls.house_expense_account.write({ 'l10n_in_tds_tcs_section_id': cls.env.ref('l10n_in_withholding.tds_section_194c').id }) cls.internet_account = ChartTemplate.ref('p2105') cls.internet_account.write({ 'l10n_in_tds_tcs_section_id': cls.env.ref('l10n_in_withholding.tds_section_194j').id }) cls.rent_account = ChartTemplate.ref('p2111') cls.rent_account.write({ 'l10n_in_tds_tcs_section_id': cls.env.ref('l10n_in_withholding.tds_section_194ib').id }) cls.sale_account = ChartTemplate.ref('p20011') cls.sale_account.write({ 'l10n_in_tds_tcs_section_id': cls.env.ref('l10n_in_withholding.tcs_section_206c1g_r').id }) cls.service_account = ChartTemplate.ref('p20021') cls.creditors_account = ChartTemplate.ref('p11211') # ==== Taxes ==== cls.tax_194c = ChartTemplate.ref('tds_20_us_194c') cls.tax_194c.write({'l10n_in_section_id': cls.env.ref('l10n_in_withholding.tds_section_194c').id}) cls.tax_194j = ChartTemplate.ref('tds_10_us_194j') cls.tax_194j.write({'l10n_in_section_id': cls.env.ref('l10n_in_withholding.tds_section_194j').id}) cls.tax_194ib = ChartTemplate.ref('tds_20_us_194ib') cls.tax_194ib.write({'l10n_in_section_id': cls.env.ref('l10n_in_withholding.tds_section_194ib').id}) cls.tax_206c1g_r = ChartTemplate.ref('tcs_5_us_206c_1g_som') cls.tax_206c1g_r.write({'l10n_in_section_id': cls.env.ref('l10n_in_withholding.tcs_section_206c1g_r').id}) country_in_id = cls.env.ref("base.in").id # ==== Partners ==== cls.partner_a.write({ 'l10n_in_pan': 'ABCPM8965E' }) cls.partner_b.write({ 'vat': '27ABCPM8965E1ZE', 'l10n_in_pan': 'ABCPM8965E' }) cls.partner_foreign_2 = cls.partner_foreign.copy() # ==== Company ==== cls.env.company.write({ 'child_ids': [ Command.create({ 'name': 'Branch A', "state_id": cls.env.ref("base.state_in_gj").id, 'account_fiscal_country_id': country_in_id, 'country_id': country_in_id, }), Command.create({ 'name': 'Branch B', "state_id": cls.env.ref("base.state_in_mh").id, 'account_fiscal_country_id': country_in_id, 'country_id': country_in_id, }), Command.create({ 'name': 'Branch C', "state_id": cls.env.ref("base.state_in_mp").id, 'account_fiscal_country_id': country_in_id, 'country_id': country_in_id, }), ], }) cls.cr.precommit.run() # load the CoA cls.branch_a, cls.branch_b, cls.branch_c = cls.env.company.child_ids def create_invoice(self, move_type=None, partner=None, invoice_date=None, amounts=None, taxes=[], company=None, accounts=[], quantities=[]): invoice = self.init_invoice( move_type=move_type or 'in_invoice', partner=partner, invoice_date=invoice_date, post=False, amounts=amounts, company=company ) for i, account in enumerate(accounts): invoice.invoice_line_ids[i].account_id = account for i, quantity in enumerate(quantities): invoice.invoice_line_ids[i].quantity = quantity for i, tax in enumerate(taxes): invoice.invoice_line_ids[i].tax_ids = tax invoice.action_post() return invoice def tds_wizard_entry(self, move, lines): tds_wizard = self.env['l10n_in.withhold.wizard'].with_context(active_model='account.move', active_ids=move.ids).create({ 'journal_id': self.env['account.journal'].search([ ('company_id', '=', self.env.company.id), ('type', '=', 'general') ], limit=1).id, 'date': move.invoice_date, }) for tax, amount in lines: self.env['l10n_in.withhold.wizard.line'].create({ 'withhold_id': tds_wizard.id, 'tax_id': tax.id, 'base': amount }) tds_wizard.action_create_and_post_withhold() def reverse_move(self, move, date): move_reversal = self.env['account.move.reversal'].with_context(active_model="account.move", active_ids=move.ids).create({ 'date': date, 'reason': 'no reason', 'journal_id': move.journal_id.id, }) return move_reversal.refund_moves() def test_tcs_tds_warning(self): ''' Test that if any of the limit is not exceeded. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2024-06-05', amounts=[29000], company=self.branch_a, accounts=[self.internet_account], quantities=[1] ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_on_exceeded_per_transaction_limit(self): ''' Test that if the per transaction limit is exceeded. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2024-06-05', amounts=[31000], company=self.branch_a, quantities=[1] ) self.assertEqual(move.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") move_1 = self.create_invoice( partner=self.partner_b, invoice_date='2024-06-05', amounts=[31000], company=self.branch_b, quantities=[1] ) self.assertEqual(move_1.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") self.create_invoice( partner=self.partner_b, invoice_date='2024-06-05', amounts=[31000], company=self.branch_b, quantities=[1] ) move_3 = self.create_invoice( partner=self.partner_b, invoice_date='2024-06-05', amounts=[31000], company=self.branch_b, quantities=[1] ) self.assertEqual(move_3.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") def test_tcs_tds_warning_on_monthly_aggregate_limit(self): ''' Test the monthly aggregate limit, the warning message should be set accordingly. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2024-06-05', amounts=[30000], company=self.branch_a, accounts=[self.rent_account] ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) move_1 = self.create_invoice( partner=self.partner_b, invoice_date='2024-07-06', amounts=[20000], company=self.branch_b, accounts=[self.rent_account] ) self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) move_2 = self.create_invoice( partner=self.partner_a, invoice_date='2024-07-16', amounts=[31000], company=self.branch_c, accounts=[self.rent_account] ) self.assertEqual(move_2.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194IB on this transaction.") move_3 = self.create_invoice( partner=self.partner_a, invoice_date='2024-09-06', amounts=[50000], company=self.branch_c, accounts=[self.rent_account] ) self.assertEqual(move_3.l10n_in_tcs_tds_warning, False) move_4 = self.create_invoice( partner=self.partner_a, invoice_date='2024-09-16', amounts=[50000], company=self.branch_c, accounts=[self.rent_account] ) self.assertEqual(move_4.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194IB on this transaction.") def test_tcs_tds_warning_partner_wiht_pan(self): ''' Test the aggregate limit when partner don't have pan number and having pan number. ''' # no pan number move = self.create_invoice( partner=self.partner_foreign, invoice_date='2024-06-05', amounts=[30000], company=self.branch_a, accounts=[self.internet_account] ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) move_1 = self.create_invoice( partner=self.partner_foreign_2, invoice_date='2024-06-05', amounts=[30000], company=self.branch_b, accounts=[self.internet_account] ) self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) # same pan number move_2 = self.create_invoice( partner=self.partner_a, invoice_date='2024-06-05', amounts=[30000], company=self.branch_a, accounts=[self.internet_account] ) self.assertEqual(move_2.l10n_in_tcs_tds_warning, False) move_3 = self.create_invoice( partner=self.partner_b, invoice_date='2024-06-05', amounts=[30000], company=self.branch_b, accounts=[self.internet_account] ) self.assertEqual(move_3.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194J on this transaction.") def test_tcs_tds_warning_on_exceeded_aggregate_limit(self): ''' Test that if the aggregate limit is exceeded. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2024-06-05', amounts=[20000], company=self.branch_a, ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) move_1 = self.create_invoice( partner=self.partner_b, invoice_date='2024-07-06', amounts=[20000], company=self.branch_b, ) self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) move_2 = self.create_invoice( partner=self.partner_a, invoice_date='2024-08-06', amounts=[31000], company=self.branch_c, ) self.assertEqual(move_2.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") move_3 = self.create_invoice( partner=self.partner_b, invoice_date='2024-09-06', amounts=[5000], company=self.branch_a, ) self.assertEqual(move_3.l10n_in_tcs_tds_warning, False) move_4 = self.create_invoice( partner=self.partner_a, invoice_date='2024-10-07', amounts=[20000], company=self.branch_b, ) self.assertEqual(move_4.l10n_in_tcs_tds_warning, False) move_5 = self.create_invoice( partner=self.partner_b, invoice_date='2024-11-08', amounts=[25000], company=self.branch_c, ) self.assertEqual(move_5.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") def test_tcs_tds_warning_on_case_of_credit_note(self): ''' Test that the aggregate limit in case of debit/credit note. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2024-09-01', amounts=[2000], company=self.branch_a, accounts=[self.internet_account] ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) move_1 = self.create_invoice( partner=self.partner_b, invoice_date='2024-09-01', amounts=[3000], company=self.branch_a, accounts=[self.internet_account] ) self.reverse_move(move, '2024-09-01') self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) move_2 = self.create_invoice( partner=self.partner_a, invoice_date='2024-09-01', amounts=[2000], company=self.branch_a, accounts=[self.internet_account] ) self.assertEqual(move_2.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_cleared_on_available_tax(self): ''' Test when a tax is added to the move line with a similar tax group as the account. ''' move = self.create_invoice( partner=self.partner_a, move_type='out_invoice', invoice_date='2022-12-12', amounts=[710000], taxes=[self.tax_206c1g_r], company=self.branch_a, ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_for_multiple_accounts_in_lines(self): ''' Test when there are multiple products in the move line and some of them have different accounts which have the different tax group as the account. ''' move = self.create_invoice( partner=self.partner_a, move_type='in_invoice', invoice_date='2022-12-12', amounts=[100000, 1100000, 710000], company=self.branch_a, accounts=[self.rent_account, self.internet_account, self.purchase_account], quantities=[15, 16, 10] ) self.assertTrue(move.l10n_in_tcs_tds_warning) move_1 = self.create_invoice( partner=self.partner_a, move_type='in_invoice', invoice_date='2022-12-12', amounts=[1000000.0, 1100000.0, 710000], company=self.branch_a, accounts=[self.rent_account, self.internet_account, self.purchase_account], ) self.tds_wizard_entry(move=move_1, lines=[(self.tax_194ib, 100000), (self.tax_194j, 100000), (self.tax_194c, 100000)]) move_1.button_draft() move_1.action_post() self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_for_if_line_has_price_zero(self): ''' Test when any invoice line has Zero ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[101000, 0], company=self.branch_a, ) self.assertEqual(move.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") move_1 = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[0], company=self.branch_a, ) self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_for_all_lines_do_not_have_taxes(self): ''' Test when tds entry created and warning will removed ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[1000, 6000], company=self.branch_a, accounts=[], quantities=[15, 16] ) self.assertEqual(move.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") self.tds_wizard_entry(move=move, lines=[(self.tax_194c, 100000)]) move.button_draft() move.action_post() self.assertEqual(move.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_for_company_branches(self): ''' Test when the aggregate limit is exceeded in case of multiple branches of the company,the warning message should be set accordingly. ''' self.create_invoice( partner=self.partner_a, invoice_date='2024-05-14', amounts=[25000], company=self.branch_a, ) self.create_invoice( partner=self.partner_b, invoice_date='2024-05-14', amounts=[25000], company=self.branch_b, ) self.create_invoice( partner=self.partner_b, invoice_date='2024-05-14', amounts=[25000], company=self.branch_c, quantities=[25] ) move = self.create_invoice( partner=self.partner_a, invoice_date='2024-05-14', amounts=[28000], company=self.branch_a, ) self.assertEqual(move.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") def test_tcs_tds_warning_tcs_use_in_bill(self): ''' Test when tcs section is used in the bill creation. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2024-05-29', amounts=[1100000], company=self.branch_a, accounts=[self.sale_account] ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_tds_use_in_invoice(self): ''' Test when tcs section is used in the bill creation. ''' move = self.create_invoice( move_type='out_invoice', partner=self.partner_a, invoice_date='2024-05-29', amounts=[110000], company=self.branch_a, ) self.assertEqual(move.l10n_in_tcs_tds_warning, False) def test_tcs_tds_warning_for_multiple_accounts_same_section_in_lines(self): ''' Test when there are multiple products in the move line and some of them have different accounts which have the same tax group as the account. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[17000, 14000], company=self.branch_a, accounts=[self.house_expense_account, self.purchase_account], ) self.assertEqual(move.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") move_1 = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[17000, 13000], company=self.branch_a, accounts=[self.house_expense_account, self.purchase_account], ) self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) move_2 = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[30000], company=self.branch_a, accounts=[self.house_expense_account], ) self.assertEqual(move_2.l10n_in_tcs_tds_warning, False) move_3 = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[10000], company=self.branch_a, ) self.assertEqual(move_3.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") def test_tcs_tds_warning_for_not_consider_draft_cancel_invoices_for_aggregate(self): ''' Test to exclude draft and canceled invoices from aggregate total calculation. ''' move = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[16000], company=self.branch_a, accounts=[self.purchase_account], ) move.button_cancel() self.assertEqual(move.l10n_in_tcs_tds_warning, False) move_1 = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[25000], company=self.branch_a, accounts=[self.purchase_account], ) self.assertEqual(move_1.l10n_in_tcs_tds_warning, False) move_2 = self.create_invoice( partner=self.partner_a, invoice_date='2022-12-12', amounts=[85000], company=self.branch_a, accounts=[self.purchase_account], ) self.assertEqual(move_2.l10n_in_tcs_tds_warning, "It's advisable to deduct TDS u/s 194C on this transaction.") def test_tcs_tds_warning_if_some_lines_has_tax(self): ''' Test when a tax is added to the some of the move line ''' move = self.create_invoice( partner=self.partner_a, move_type='out_invoice', invoice_date='2022-12-12', amounts=[710000, 710000], taxes=[self.tax_206c1g_r], company=self.branch_a, ) self.assertEqual(move.l10n_in_tcs_tds_warning, "It's advisable to collect TCS u/s 206C(1G) Remittance on this transaction.")