From a3cd6b3bf45c569d982f8f6b9e8594b82efbbdcf Mon Sep 17 00:00:00 2001 From: Kitti U Date: Sun, 31 Oct 2021 21:23:37 +0700 Subject: [PATCH] Merge l10n_th_account_advance_clearing to l10n_th_account_expense_tax --- .../security/ir.model.access.csv | 1 + .../views/hr_expense_view.xml | 5 +- .../models/__init__.py | 1 + .../models/account_move.py | 33 ++++++- .../models/hr_expense_sheet.py | 96 +++++++++++++++++++ .../readme/DESCRIPTION.rst | 4 +- .../views/hr_expense_view.xml | 18 ++++ 7 files changed, 153 insertions(+), 5 deletions(-) create mode 100644 l10n_th_account_tax_expense/models/hr_expense_sheet.py diff --git a/l10n_th_account_tax/security/ir.model.access.csv b/l10n_th_account_tax/security/ir.model.access.csv index b00ae50f9..d9eade12a 100644 --- a/l10n_th_account_tax/security/ir.model.access.csv +++ b/l10n_th_account_tax/security/ir.model.access.csv @@ -4,6 +4,7 @@ access_account_move_tax_invoice_portal,account.move.tax.invoice portal,model_acc access_account_move_tax_invoice_manager,account.move.tax.invoice manager,model_account_move_tax_invoice,account.group_account_manager,1,0,0,0 access_account_move_tax_invoice_user,account.move.tax.invoice user,model_account_move_tax_invoice,base.group_user,1,1,1,0 access_account_withholding_tax,account.withholding.tax,model_account_withholding_tax,account.group_account_invoice,1,1,1,1 +access_account_withholding_tax_user,account.withholding.tax.user,model_account_withholding_tax,base.group_user,1,0,0,0 access_personal_income_tax,access_personal_income_tax,model_personal_income_tax,account.group_account_user,1,1,1,1 access_personal_income_tax_user,access_personal_income_tax_user,model_personal_income_tax,,1,0,0,0 access_personal_income_tax_rate,access_personal_income_tax_rate,model_personal_income_tax_rate,account.group_account_user,1,1,1,1 diff --git a/l10n_th_account_tax_advance_clearing/views/hr_expense_view.xml b/l10n_th_account_tax_advance_clearing/views/hr_expense_view.xml index d9f7c9d80..b2df8b90f 100644 --- a/l10n_th_account_tax_advance_clearing/views/hr_expense_view.xml +++ b/l10n_th_account_tax_advance_clearing/views/hr_expense_view.xml @@ -10,10 +10,11 @@ diff --git a/l10n_th_account_tax_expense/models/__init__.py b/l10n_th_account_tax_expense/models/__init__.py index 7b5ce8aff..f5feaa8e8 100644 --- a/l10n_th_account_tax_expense/models/__init__.py +++ b/l10n_th_account_tax_expense/models/__init__.py @@ -2,3 +2,4 @@ from . import account_move from . import hr_expense +from . import hr_expense_sheet diff --git a/l10n_th_account_tax_expense/models/account_move.py b/l10n_th_account_tax_expense/models/account_move.py index 4da61cb77..4df9e5d52 100644 --- a/l10n_th_account_tax_expense/models/account_move.py +++ b/l10n_th_account_tax_expense/models/account_move.py @@ -7,8 +7,38 @@ class AccountMove(models.Model): _inherit = "account.move" def _post(self, soft=True): + res = super()._post(soft) + self._assign_tax_invoice() + self._reconcile_withholding_tax_entry() + return res + + def _reconcile_withholding_tax_entry(self): + """ Re-Reconciliation, ensure the wht_move is taken into account """ + for move in self: + clearing = self.env["hr.expense.sheet"].search( + [("wht_move_id", "=", move.id)] + ) + if not clearing: + continue + clearing.ensure_one() + move_lines = clearing.account_move_id.line_ids + accounts = move_lines.mapped("account_id").filtered("reconcile") + # Find clearing and advance moves to unreconcile first + r_lines = clearing.account_move_id.line_ids.filtered( + lambda l: l.account_id.id in accounts.ids + ) + md_lines = r_lines.mapped("matched_debit_ids.debit_move_id") + mc_lines = r_lines.mapped("matched_credit_ids.credit_move_id") + # Removes reconcile + (r_lines + md_lines + mc_lines).remove_move_reconcile() + # Re-reconcile again this time with the wht_tax JV + wht_lines = move.line_ids.filtered( + lambda l: l.account_id.id in accounts.ids + ) + (r_lines + wht_lines + md_lines + mc_lines).reconcile() + + def _assign_tax_invoice(self): """ Use Bill Reference and Date from Expense Line as Tax Invoice """ - # Expense Taxes for move in self: for tax_invoice in move.tax_invoice_ids.filtered( lambda l: l.tax_line_id.type_tax_use == "purchase" @@ -25,4 +55,3 @@ def _post(self, soft=True): bill_partner = tax_invoice.move_line_id.expense_id.bill_partner_id if bill_partner: tax_invoice.write({"partner_id": bill_partner.id}) - return super()._post(soft) diff --git a/l10n_th_account_tax_expense/models/hr_expense_sheet.py b/l10n_th_account_tax_expense/models/hr_expense_sheet.py new file mode 100644 index 000000000..1feb41faf --- /dev/null +++ b/l10n_th_account_tax_expense/models/hr_expense_sheet.py @@ -0,0 +1,96 @@ +# Copyright 2021 Ecosoft Co., Ltd (http://ecosoft.co.th/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) +from odoo import _, fields, models +from odoo.exceptions import UserError + + +class HrExpenseSheet(models.Model): + _inherit = "hr.expense.sheet" + + wht_move_id = fields.Many2one( + comodel_name="account.move", + string="Withholding Tax JV", + ondelete="set null", + copy=False, + readonly=True, + help="For case clear advance, a JV can be created to record withholding tax", + ) + has_wht = fields.Boolean( + compute="_compute_has_wht", + ) + + def _compute_has_wht(self): + for rec in self: + rec.has_wht = len(rec.expense_line_ids.mapped("wht_tax_id")) > 0 + + def action_create_withholding_tax_entry(self): + """From expense sheet with WHT lines, this action + helps create new JV with default withholding entries""" + active_id = self.env.context.get("active_id") + sheet = self.env["hr.expense.sheet"].browse(active_id) + sheet.ensure_one() + # Validation + if sheet.state not in ("done", "post"): + raise UserError(_("Only posted or paid expense report can create JV")) + if sheet.wht_move_id: + raise UserError(_("Already created withholding tax JV")) + # Window action + action = self.env.ref("account.action_move_journal_line") + result = action.sudo().read()[0] + view = self.env.ref("account.view_move_form", False) + result["views"] = [(view and view.id or False, "form")] + # Create wht JV + move_vals = sheet._prepare_withholding_tax_entry() + move = self.env["account.move"].create(move_vals) + sheet.wht_move_id = move + result["res_id"] = move.id + return result + + def _prepare_withholding_tax_entry(self): + self.ensure_one() + # Prepare Dr. Advance, Cr. WHT lines + line_vals_list = [] + move_lines = self.account_move_id.mapped("line_ids") + # Cr. WHT Lines + wht_move_lines = move_lines.filtered("wht_tax_id") + currency = self.env.company.currency_id + deduction_list, amount_deduct = wht_move_lines._prepare_deduction_list( + currency=currency + ) + for deduction in deduction_list: + line_vals_list.append( + { + "name": deduction["name"], + "amount_currency": -deduction["amount"], + "currency_id": currency.id, + "debit": 0.0, + "credit": deduction["amount"], + "partner_id": deduction["partner_id"], + "account_id": deduction["account_id"], + "wht_tax_id": deduction["wht_tax_id"], + "tax_base_amount": deduction["wht_amount_base"], + } + ) + accounts = move_lines.mapped("account_id").filtered("reconcile") + # Dr. Reconcilable Account (i.e., AP, Advance) + partner_id = self.employee_id.sudo().address_home_id.commercial_partner_id.id + for account in accounts: + line_vals_list.append( + { + "name": account.name, + "amount_currency": amount_deduct, + "currency_id": currency.id, + "debit": amount_deduct, # Sum of all credit + "credit": 0.0, + "partner_id": partner_id, + "account_id": account.id, + } + ) + amount_deduct = 0.0 + # Create JV + move_vals = { + "move_type": "entry", + "ref": self.account_move_id.display_name, + "line_ids": [(0, 0, line_vals) for line_vals in line_vals_list], + } + return move_vals diff --git a/l10n_th_account_tax_expense/readme/DESCRIPTION.rst b/l10n_th_account_tax_expense/readme/DESCRIPTION.rst index d979f2ad2..e2f643bec 100644 --- a/l10n_th_account_tax_expense/readme/DESCRIPTION.rst +++ b/l10n_th_account_tax_expense/readme/DESCRIPTION.rst @@ -1,6 +1,8 @@ -This module make sure that Expense will also comply with Tax Invoice concept of l10n_th_tax. +This module make sure that Expense will also comply with Tax Invoice concept of l10n_th_account_tax. In case expense has VAT, * Expense's Bill Reference and Date will be used as Tax Invoice Number and Tax Invoice Date * Without Bill Reference, Post Journal Entry is not allowed + +This module also provide addition step to create withholding tax journal entry. diff --git a/l10n_th_account_tax_expense/views/hr_expense_view.xml b/l10n_th_account_tax_expense/views/hr_expense_view.xml index 56762ba58..6e1a00083 100644 --- a/l10n_th_account_tax_expense/views/hr_expense_view.xml +++ b/l10n_th_account_tax_expense/views/hr_expense_view.xml @@ -31,6 +31,12 @@ hr.expense.sheet + + + + + + Create Withholding Tax JV + + + form + code + + action = env['hr.expense.sheet'].action_create_withholding_tax_entry() + + +