Skip to content

Commit

Permalink
[FIX] l10n_it_withholding_tax: pay multiple invoices with expenses
Browse files Browse the repository at this point in the history
Co-authored-by: Simone Rubino <[email protected]>
  • Loading branch information
sergiocorato and SirAionTech committed Oct 22, 2024
1 parent 1747779 commit ae503f3
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 50 deletions.
98 changes: 83 additions & 15 deletions l10n_it_withholding_tax/models/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ def _wt_get_paying_invoice(self, move_lines):
# If we are reconciling a vendor bill and its refund,
# we do not need to generate Withholding Tax Moves
# or change the reconciliation amount
in_refunding = len(invoices) == 2 and set(invoices.mapped("move_type")) == {
"in_invoice",
"in_refund",
}
in_refunding = invoices._wt_in_refunding()
if not in_refunding:
paying_invoice = first(invoices)
else:
Expand All @@ -72,30 +69,50 @@ def create(self, vals):
debit_move_line, credit_move_line = self._wt_get_move_lines(vals)
move_lines = debit_move_line | credit_move_line
paying_invoice = self._wt_get_paying_invoice(move_lines)
reconcile_existing = False
# Limit value of reconciliation
if (
paying_invoice
and paying_invoice.withholding_tax
and paying_invoice.amount_net_pay
and paying_invoice.amount_net_pay_residual
):
# We must consider amount in foreign currency, if present
# Note that this is always executed, for every reconciliation.
# Thus, we must not change amount when not in withholding tax case
amount = vals.get("amount_currency") or vals.get("amount")
digits_rounding_precision = paying_invoice.company_id.currency_id.rounding
if amount == 0.0:
# it's a reconciliation with an existing move line
if (
float_compare(
abs(debit_move_line.amount_residual),
abs(credit_move_line.amount_residual),
precision_rounding=digits_rounding_precision,
)
== 0
):
amount = abs(move_lines[0].amount_residual)
vals.update(

Check warning on line 95 in l10n_it_withholding_tax/models/account.py

View check run for this annotation

Codecov / codecov/patch

l10n_it_withholding_tax/models/account.py#L94-L95

Added lines #L94 - L95 were not covered by tests
{
"amount": amount,
"credit_amount_currency": amount,
"debit_amount_currency": amount,
}
)
reconcile_existing = True

Check warning on line 102 in l10n_it_withholding_tax/models/account.py

View check run for this annotation

Codecov / codecov/patch

l10n_it_withholding_tax/models/account.py#L102

Added line #L102 was not covered by tests
if (
float_compare(
amount,
paying_invoice.amount_net_pay,
paying_invoice.amount_net_pay_residual,
precision_rounding=digits_rounding_precision,
)
== 1
):
vals.update(
{
"amount": paying_invoice.amount_net_pay,
"credit_amount_currency": paying_invoice.amount_net_pay,
"debit_amount_currency": paying_invoice.amount_net_pay,
"amount": paying_invoice.amount_net_pay_residual,
"credit_amount_currency": paying_invoice.amount_net_pay_residual,
"debit_amount_currency": paying_invoice.amount_net_pay_residual,
}
)

Expand All @@ -106,11 +123,26 @@ def create(self, vals):

moves = move_lines.move_id
lines = self.env["account.move.line"].search(
[("withholding_tax_generated_by_move_id", "in", moves.ids)]
[
("withholding_tax_generated_by_move_id", "in", moves.ids),
("balance", "=", abs(vals.get("amount"))),
]
)
if not lines:
for move in moves.filtered(lambda x: x.withholding_tax_amount):
lines = self.env["account.move.line"].search(
[
("withholding_tax_generated_by_move_id", "in", moves.ids),
("balance", "=", abs(move.withholding_tax_amount)),
("name", "=ilike", move.name),
]
)
if lines:
reconcile_existing = True

Check warning on line 141 in l10n_it_withholding_tax/models/account.py

View check run for this annotation

Codecov / codecov/patch

l10n_it_withholding_tax/models/account.py#L141

Added line #L141 was not covered by tests
if lines:
is_wt_move = True
reconcile.generate_wt_moves(is_wt_move, lines)
if not reconcile_existing:
reconcile.generate_wt_moves(is_wt_move, lines)

Check warning on line 145 in l10n_it_withholding_tax/models/account.py

View check run for this annotation

Codecov / codecov/patch

l10n_it_withholding_tax/models/account.py#L145

Added line #L145 was not covered by tests
else:
is_wt_move = False

Expand All @@ -127,7 +159,8 @@ def create(self, vals):
)
):
# and not wt_existing_moves\
reconcile.generate_wt_moves(is_wt_move)
if not reconcile_existing:
reconcile.generate_wt_moves(is_wt_move)

return reconcile

Expand All @@ -152,7 +185,7 @@ def generate_wt_moves(self, is_wt_move, lines=None):
wt_statements = wt_statement_obj.browse()
rec_line_statement = rec_line_model.browse()
for rec_line in rec_lines:
domain = [("move_id", "=", rec_line.move_id.id)]
domain = [("invoice_id", "=", rec_line.move_id.id)]
wt_statements = wt_statement_obj.search(domain)
if wt_statements:
rec_line_statement = rec_line
Expand Down Expand Up @@ -470,7 +503,6 @@ def create_wt_statement(self):
val = {
"wt_type": "",
"date": self.date,
"move_id": self.id,
"invoice_id": self.id,
"partner_id": self.partner_id.id,
"withholding_tax_id": inv_wt.withholding_tax_id.id,
Expand Down Expand Up @@ -507,7 +539,7 @@ def _wt_unlink_statements(self):
if posted_moves:
statements = self.env["withholding.tax.statement"].search(
[
("move_id", "in", posted_moves.ids),
("invoice_id", "in", posted_moves.ids),
],
)
statements.unlink()
Expand All @@ -518,6 +550,12 @@ def write(self, vals):
self._wt_unlink_statements()
return super().write(vals)

def _wt_in_refunding(self):
return len(self) == 2 and set(self.mapped("move_type")) == {
"in_invoice",
"in_refund",
}


class AccountMoveLine(models.Model):
_inherit = "account.move.line"
Expand Down Expand Up @@ -558,6 +596,36 @@ def remove_move_reconcile(self):

return super(AccountMoveLine, self).remove_move_reconcile()

def _prepare_reconciliation_partials(self):
wt_move_lines = self.filtered(lambda x: x.withholding_tax_amount != 0)
if not wt_move_lines:
return super()._prepare_reconciliation_partials()
credit_lines = self.filtered(lambda line: line.credit)
debit_line = self - credit_lines
partials_vals_list = []
for credit_line in credit_lines:
total_amount_payment = debit_line.balance
invoices = (credit_line | debit_line).move_id.filtered(
lambda move: move.is_invoice()
)
in_refunding = invoices._wt_in_refunding()
residual_amount = credit_line.move_id.amount_net_pay_residual
if not in_refunding and total_amount_payment > residual_amount:
total_amount_payment -= residual_amount
else:
residual_amount = total_amount_payment
partials_vals_list.append(
{
"amount": residual_amount,
"debit_amount_currency": residual_amount,
"credit_amount_currency": residual_amount,
"debit_move_id": debit_line.id,
"credit_move_id": credit_line.id,
}
)

return partials_vals_list

@api.model
def _default_withholding_tax(self):
result = []
Expand Down
9 changes: 4 additions & 5 deletions l10n_it_withholding_tax/models/withholding_tax.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ def _compute_total(self):
store=True,
compute="_compute_type",
)
move_id = fields.Many2one("account.move", "Account move", ondelete="cascade")
invoice_id = fields.Many2one("account.move", "Invoice", ondelete="cascade")
partner_id = fields.Many2one("res.partner", "Partner")
withholding_tax_id = fields.Many2one("withholding.tax", string="Withholding Tax")
Expand All @@ -243,12 +242,12 @@ def _compute_total(self):
)
move_ids = fields.One2many("withholding.tax.move", "statement_id", "Moves")

@api.depends("move_id.line_ids.account_id.user_type_id.type")
@api.depends("invoice_id.line_ids.account_id.user_type_id.type")
def _compute_type(self):
for st in self:
if st.move_id:
if st.invoice_id:
domain = [
("move_id", "=", st.move_id.id),
("move_id", "=", st.invoice_id.id),
("account_id.user_type_id.type", "=", "payable"),
]
lines = self.env["account.move.line"].search(domain)
Expand Down Expand Up @@ -279,7 +278,7 @@ def get_wt_competence(self, amount_reconcile):
)
if st.invoice_id.move_type in ["in_refund", "out_refund"]:
amount_wt = -1 * amount_wt
elif st.move_id:
elif st.invoice_id:
tax_data = st.withholding_tax_id.compute_tax(amount_reconcile)
amount_wt = tax_data["tax"]
return amount_wt
Expand Down
Loading

0 comments on commit ae503f3

Please sign in to comment.