From bacb86552259ffca92b83483d62823ec822cb723 Mon Sep 17 00:00:00 2001 From: Saran440 Date: Fri, 24 Nov 2023 10:44:11 +0700 Subject: [PATCH] [FIX] clear morethan advance, accounting is mistake --- .../models/hr_expense.py | 155 +++++++----------- .../models/hr_expense_sheet.py | 78 +++++++-- .../wizard/account_payment_register.py | 5 +- 3 files changed, 128 insertions(+), 110 deletions(-) diff --git a/hr_expense_advance_clearing/models/hr_expense.py b/hr_expense_advance_clearing/models/hr_expense.py index 4fdf738cd..bb1f46631 100644 --- a/hr_expense_advance_clearing/models/hr_expense.py +++ b/hr_expense_advance_clearing/models/hr_expense.py @@ -3,7 +3,6 @@ from odoo import _, api, fields, models from odoo.exceptions import ValidationError -from odoo.tools import float_compare class HrExpense(models.Model): @@ -27,12 +26,13 @@ class HrExpense(models.Model): help="Expense created from this advance expense line", ) + def _get_product_advance(self): + return self.env.ref("hr_expense_advance_clearing.product_emp_advance", False) + @api.constrains("advance") def _check_advance(self): for expense in self.filtered("advance"): - emp_advance = self.env.ref( - "hr_expense_advance_clearing.product_emp_advance" - ) + emp_advance = expense._get_product_advance() if not emp_advance.property_account_expense_id: raise ValidationError( _("Employee advance product has no payable account") @@ -55,100 +55,57 @@ def _check_advance(self): def onchange_advance(self): self.tax_ids = False if self.advance: - self.product_id = self.env.ref( - "hr_expense_advance_clearing.product_emp_advance" - ) - - def _get_account_move_line_values(self): - """Create move line (journal) from clearing""" - move_line_values_by_expense = {} - for expense in self: - advance_to_clear = expense.sheet_id.advance_sheet_residual - move_line_name = ( - expense.employee_id.name + ": " + expense.name.split("\n")[0][:64] - ) - account_src = expense.account_id - account_dst = expense._get_expense_account_destination() - account_date = ( - expense.date - or expense.sheet_id.accounting_date - or fields.Date.context_today(expense) - ) + self.product_id = self._get_product_advance() - move_line_values = [] - unit_amount = expense.unit_amount or expense.total_amount - quantity = expense.quantity if expense.unit_amount else 1 - taxes = expense.tax_ids.with_context(round=True).compute_all( - unit_amount, expense.currency_id, quantity, expense.product_id - ) - total_amount = 0.0 - total_amount_currency = 0.0 - partner_id = ( - expense.employee_id.sudo().address_home_id.commercial_partner_id.id - ) - # source move line - balance = expense.total_amount_company - expense.amount_tax_company - amount_currency = expense.total_amount - expense.amount_tax - move_line_src = { - "name": move_line_name, - "quantity": expense.quantity or 1, - "debit": balance if balance > 0 else 0, - "credit": -balance if balance < 0 else 0, - "amount_currency": amount_currency, - "account_id": account_src.id, - "product_id": expense.product_id.id, - "product_uom_id": expense.product_uom_id.id, - "analytic_distribution": expense.analytic_distribution, - "expense_id": expense.id, - "partner_id": partner_id, - "tax_ids": [(6, 0, expense.tax_ids.ids)], - "tax_tag_ids": [(6, 0, taxes["base_tags"])], - "currency_id": expense.currency_id.id, - } - move_line_values.append(move_line_src) - total_amount -= expense.total_amount_company - total_amount_currency -= expense.total_amount + def _get_move_line_src(self, move_line_name, partner_id): + self.ensure_one() + unit_amount = self.unit_amount or self.total_amount + quantity = self.quantity if self.unit_amount else 1 + taxes = self.tax_ids.with_context(round=True).compute_all( + unit_amount, self.currency_id, quantity, self.product_id + ) + amount_currency = self.total_amount - self.amount_tax + balance = self.total_amount_company - self.amount_tax_company + ml_src_dict = { + "name": move_line_name, + "quantity": quantity, + "debit": balance if balance > 0 else 0, + "credit": -balance if balance < 0 else 0, + "amount_currency": amount_currency, + "account_id": self.account_id.id, + "product_id": self.product_id.id, + "product_uom_id": self.product_uom_id.id, + "analytic_distribution": self.analytic_distribution, + "expense_id": self.id, + "partner_id": partner_id, + "tax_ids": [(6, 0, self.tax_ids.ids)], + "tax_tag_ids": [(6, 0, taxes["base_tags"])], + "currency_id": self.currency_id.id, + } + return ml_src_dict - # destination move line - emp_advance = self.env.ref( - "hr_expense_advance_clearing.product_emp_advance" - ) - move_line_dst = { - "name": move_line_name, - "debit": total_amount > 0 and total_amount, - "credit": total_amount < 0 and -total_amount, - "account_id": emp_advance.property_account_expense_id.id, - "date_maturity": account_date, - "amount_currency": total_amount_currency, - "currency_id": expense.currency_id.id, - "expense_id": expense.id, - "partner_id": partner_id, - } - # Check clearing > advance, it will split line - credit = move_line_dst["credit"] - # cr payable -> cr advance - remain_payable = 0.0 - payable_move_line = [] - if ( - float_compare( - credit, - advance_to_clear, - precision_rounding=expense.currency_id.rounding, - ) - == 1 - ): - remain_payable = credit - advance_to_clear - move_line_dst["credit"] = advance_to_clear - move_line_dst["amount_currency"] = -advance_to_clear - advance_to_clear = 0.0 - # extra payable line - payable_move_line = move_line_dst.copy() - payable_move_line["credit"] = remain_payable - payable_move_line["amount_currency"] = -remain_payable - payable_move_line["account_id"] = account_dst - # Add destination first - move_line_values.append(move_line_dst) - if payable_move_line: - move_line_values.append(payable_move_line) - move_line_values_by_expense[expense.id] = move_line_values - return move_line_values_by_expense + def _get_move_line_dst( + self, + move_line_name, + partner_id, + total_amount, + total_amount_currency, + account_advance, + ): + account_date = ( + self.date + or self.sheet_id.accounting_date + or fields.Date.context_today(self) + ) + ml_dst_dict = { + "name": move_line_name, + "debit": total_amount > 0 and total_amount, + "credit": total_amount < 0 and -total_amount, + "account_id": account_advance.id, + "date_maturity": account_date, + "amount_currency": total_amount_currency, + "currency_id": self.currency_id.id, + "expense_id": self.id, + "partner_id": partner_id, + } + return ml_dst_dict diff --git a/hr_expense_advance_clearing/models/hr_expense_sheet.py b/hr_expense_advance_clearing/models/hr_expense_sheet.py index 8d3662801..f4ac980f4 100644 --- a/hr_expense_advance_clearing/models/hr_expense_sheet.py +++ b/hr_expense_advance_clearing/models/hr_expense_sheet.py @@ -73,12 +73,13 @@ def _compute_payment_state(self): sheet.payment_state = "paid" return res + def _get_product_advance(self): + return self.env.ref("hr_expense_advance_clearing.product_emp_advance", False) + @api.depends("account_move_id.line_ids.amount_residual") def _compute_clearing_residual(self): - emp_advance = self.env.ref( - "hr_expense_advance_clearing.product_emp_advance", False - ) for sheet in self: + emp_advance = sheet._get_product_advance() residual_company = 0.0 if emp_advance: for line in sheet.sudo().account_move_id.line_ids: @@ -99,7 +100,6 @@ def _compute_clearing_count(self): def action_sheet_move_create(self): res = super().action_sheet_move_create() - emp_advance = self.env.ref("hr_expense_advance_clearing.product_emp_advance") for sheet in self: if not sheet.advance_sheet_id: continue @@ -113,6 +113,7 @@ def action_sheet_move_create(self): sheet.account_move_id.line_ids | sheet.advance_sheet_id.account_move_id.line_ids ) + emp_advance = sheet._get_product_advance() account_id = emp_advance.property_account_expense_id.id adv_move_lines = ( self.env["account.move.line"] @@ -145,6 +146,68 @@ def action_sheet_move_create(self): ) return res + def _get_move_line_vals(self): + self.ensure_one() + move_line_vals = [] + advance_to_clear = self.advance_sheet_residual + emp_advance = self._get_product_advance() + account_advance = emp_advance.property_account_expense_id + for expense in self.expense_line_ids: + move_line_name = ( + expense.employee_id.name + ": " + expense.name.split("\n")[0][:64] + ) + total_amount = 0.0 + total_amount_currency = 0.0 + partner_id = ( + expense.employee_id.sudo().address_home_id.commercial_partner_id.id + ) + # source move line + move_line_src = expense._get_move_line_src(move_line_name, partner_id) + move_line_values = [move_line_src] + total_amount -= expense.total_amount_company + total_amount_currency -= expense.total_amount + + # destination move line + move_line_dst = expense._get_move_line_dst( + move_line_name, + partner_id, + total_amount, + total_amount_currency, + account_advance, + ) + # Check clearing > advance, it will split line + credit = move_line_dst["credit"] + # cr payable -> cr advance + remain_payable = 0.0 + payable_move_line = [] + if ( + float_compare( + credit, + advance_to_clear, + precision_rounding=expense.currency_id.rounding, + ) + == 1 + ): + remain_payable = credit - advance_to_clear + move_line_dst["credit"] = advance_to_clear + move_line_dst["amount_currency"] = -advance_to_clear + advance_to_clear = 0.0 + # extra payable line + payable_move_line = move_line_dst.copy() + payable_move_line["credit"] = remain_payable + payable_move_line["amount_currency"] = -remain_payable + payable_move_line[ + "account_id" + ] = expense._get_expense_account_destination() + else: + advance_to_clear -= credit + # Add destination first + move_line_values.append(move_line_dst) + if payable_move_line: + move_line_values.append(payable_move_line) + move_line_vals.extend(move_line_values) + return move_line_vals + def _prepare_bill_vals(self): """create journal entry instead of bills when clearing document""" self.ensure_one() @@ -157,12 +220,7 @@ def _prepare_bill_vals(self): _("Advance: %s has no amount to clear") % (self.name) ) res["move_type"] = "entry" - move_line_vals = [] - - for expense in self.expense_line_ids: - # get move line values - move_line_values_by_expense = expense._get_account_move_line_values() - move_line_vals.extend(move_line_values_by_expense.get(expense.id)) + move_line_vals = self._get_move_line_vals() res["line_ids"] = [Command.create(x) for x in move_line_vals] return res diff --git a/hr_expense_advance_clearing/wizard/account_payment_register.py b/hr_expense_advance_clearing/wizard/account_payment_register.py index 99d15e990..b1606ad25 100644 --- a/hr_expense_advance_clearing/wizard/account_payment_register.py +++ b/hr_expense_advance_clearing/wizard/account_payment_register.py @@ -65,6 +65,9 @@ def default_get(self, fields_list): return self._default_return_advance(fields_list) return super().default_get(fields_list) + def _get_product_advance(self): + return self.env.ref("hr_expense_advance_clearing.product_emp_advance", False) + def _validate_over_return(self): """Actual remaining = amount to clear - clear pending and it is not legit to return more than remaining""" @@ -113,7 +116,7 @@ def expense_post_return_advance(self): ctx = self._context.copy() ctx.update({"skip_account_move_synchronization": True}) expense_sheet = move_ids.line_ids.expense_id.sheet_id - emp_advance = self.env.ref("hr_expense_advance_clearing.product_emp_advance") + emp_advance = self._get_product_advance() advance_account = emp_advance.property_account_expense_id # Create return advance and post it batches = self._get_batches()