Odoo18-Base/addons/l10n_it_edi_withholding/models/account_move.py
2025-03-10 11:12:23 +07:00

97 lines
5.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
from collections import namedtuple
from odoo import api, fields, models
_logger = logging.getLogger(__name__)
class AccountMove(models.Model):
_inherit = 'account.move'
l10n_it_amount_vat_signed = fields.Monetary(string='VAT', compute='_compute_amount_extended', currency_field='company_currency_id')
l10n_it_amount_pension_fund_signed = fields.Monetary(string='Pension Fund', compute='_compute_amount_extended', currency_field='company_currency_id')
l10n_it_amount_withholding_signed = fields.Monetary(string='Withholding', compute='_compute_amount_extended', currency_field='company_currency_id')
l10n_it_amount_before_withholding_signed = fields.Monetary(string='Total Before Withholding', compute='_compute_amount_extended', currency_field='company_currency_id')
@api.depends('amount_total_signed')
def _compute_amount_extended(self):
for move in self:
totals = dict(vat=0.0, withholding=0.0, pension_fund=0.0)
if move.is_invoice(True):
for line in [line for line in move.line_ids if line.tax_line_id]:
totals[line.tax_line_id._l10n_it_get_tax_kind()] -= line.balance
move.l10n_it_amount_vat_signed = totals['vat']
move.l10n_it_amount_withholding_signed = totals['withholding']
move.l10n_it_amount_pension_fund_signed = totals['pension_fund']
move.l10n_it_amount_before_withholding_signed = move.amount_untaxed_signed + totals['vat'] + totals['pension_fund']
def _l10n_it_edi_filter_fatturapa_tax_details(self, line, tax_values):
"""Filters tax details to only include the positive amounted lines regarding VAT taxes."""
repartition_line = tax_values['tax_repartition_line']
repartition_line_vat = repartition_line.tax_id._l10n_it_filter_kind('vat')
return repartition_line.factor_percent >= 0 and repartition_line_vat and repartition_line_vat.amount >= 0
def _prepare_fatturapa_export_values(self):
"""Add withholding and pension_fund features."""
template_values = super()._prepare_fatturapa_export_values()
# Withholding tax data
WithholdingTaxData = namedtuple('TaxData', ['tax', 'tax_amount'])
withholding_lines = self.line_ids.filtered(lambda x: x.tax_line_id._l10n_it_filter_kind('withholding'))
withholding_values = [WithholdingTaxData(x.tax_line_id, abs(x.balance)) for x in withholding_lines]
# Eventually fix the total as it must be computed before applying the Withholding.
# Withholding amount is negatively signed, so we need to subtract it
document_total = template_values['document_total']
document_total -= self.l10n_it_amount_withholding_signed
# Pension fund tax data, I need the base amount so I have to sum the amounts of the lines with the tax
PensionFundTaxData = namedtuple('TaxData', ['tax', 'base_amount', 'tax_amount', 'vat_tax', 'withholding_tax'])
pension_fund_lines = self.line_ids.filtered(lambda line: line.tax_line_id._l10n_it_filter_kind('pension_fund'))
pension_fund_mapping = {}
for line in self.line_ids:
pension_fund_tax = line.tax_ids._l10n_it_filter_kind('pension_fund')
if pension_fund_tax:
pension_fund_mapping[pension_fund_tax.id] = (line.tax_ids._l10n_it_filter_kind('vat'), line.tax_ids._l10n_it_filter_kind('withholding'))
# Pension fund taxes in the XML must have a reference to their VAT tax (Aliquota tag)
pension_fund_values = []
enasarco_taxes = []
for line in pension_fund_lines:
# Enasarco must be treated separately
if line.tax_line_id.l10n_it_pension_fund_type == 'TC07':
enasarco_taxes.append(line.tax_line_id)
continue
pension_fund_tax = line.tax_line_id
# Here we are supposing that the same pension_fund is always associated to the same VAT and Withholding taxes
# That's also what the "Aliquota" tag seems to imply in the XML.
vat_tax, withholding_tax = pension_fund_mapping[pension_fund_tax.id]
pension_fund_values.append(PensionFundTaxData(pension_fund_tax, line.tax_base_amount, abs(line.balance), vat_tax, withholding_tax))
# Enasarco pension fund must be expressed in the AltriDatiGestionali at the line detail level
enasarco_values = False
if enasarco_taxes:
enasarco_values = {}
enasarco_details = self._prepare_edi_tax_details(filter_to_apply=lambda line, tax_values: self.env['account.tax'].browse([tax_values['id']]).l10n_it_pension_fund_type == 'TC07')
for detail in enasarco_details['tax_details_per_record'].values():
for subdetail in detail['tax_details'].values():
# Withholdings are removed from the total, we have to re-add them
document_total += abs(subdetail['tax_amount'])
line = subdetail['records'].pop()
enasarco_values[line.id] = {
'amount': subdetail['tax'].amount,
'tax_amount': abs(subdetail['tax_amount']),
}
# Update the template_values that will be read while rendering
template_values.update({
'withholding_values': withholding_values,
'pension_fund_values': pension_fund_values,
'enasarco_values': enasarco_values,
'document_total': document_total,
})
return template_values