Files
enterprise-addons/l10n_it_reports/models/tax_report.py
T

166 lines
9.8 KiB
Python

from dateutil.relativedelta import relativedelta
from lxml import etree
from markupsafe import Markup
from odoo import _, fields, models
from odoo.tools import date_utils, file_open
class ItalianReportCustomHandler(models.AbstractModel):
_name = 'l10n_it.monthly.tax.report.handler'
_inherit = 'account.tax.report.handler'
_description = 'Italian Monthly Tax Report Custom Handler'
def print_tax_report_to_xml(self, options):
view_id = self.env.ref('l10n_it_reports.monthly_tax_report_xml_export_wizard_view').id
return {
'name': _('XML Export Options'),
'view_mode': 'form',
'views': [[view_id, 'form']],
'res_model': 'l10n_it_reports.monthly.tax.report.xml.export.wizard',
'type': 'ir.actions.act_window',
'target': 'new',
'context': dict(self.env.context, l10n_it_reports_monthly_tax_report_options=options),
}
def export_tax_report_to_xml(self, options):
xml_export_data = self._get_xml_export_data(options)
xml_content = self.env["ir.qweb"]._render("l10n_it_reports.tax_report_export_template", xml_export_data)
xml_content = Markup("""<?xml version="1.0" encoding="UTF-8" standalone="yes"?>""") + xml_content
xml_content = xml_content.encode()
with file_open("l10n_it_reports/data/xml_export/validation/fornituraIvp_2018_v1.xsd", 'rb') as xsd:
xsd_schema = etree.XMLSchema(etree.parse(xsd))
try:
xsd_schema.assertValid(etree.fromstring(xml_content))
except etree.DocumentInvalid as xml_errors:
self.env['bus.bus']._sendone(
self.env.user.partner_id,
'simple_notification',
{
'type': 'warning',
'title': _('XML Validation Error'),
'message': _(
"Some values will not pass the authority's validation, please check them before submitting your file: %s",
[error.path.split(":")[-1] for error in xml_errors.error_log]
),
'sticky': True,
},
)
return {
"file_name": f"IT{xml_export_data['taxpayer_code']}_LI_{xml_export_data['identificativo']}.xml",
"file_content": xml_content,
"file_type": "xml",
}
def _get_xml_export_data(self, options):
options_date_to = fields.Date.from_string(options["date"]["date_to"])
report = self.env["account.report"].browse(options["report_id"])
company = report._get_sender_company_for_export(options)
quarterly = self.env.company.account_return_periodicity == 'trimester'
colname_to_idx = {col['expression_label']: idx for idx, col in enumerate(options.get('columns', []))}
if quarterly:
report_lines_data_per_month = {0: {}}
quarter_report_lines = report._get_lines(options)
quarter_report_expressions = self.env['account.report.expression'].search([('report_line_id', 'in', [line['columns'][0]['report_line_id'] for line in quarter_report_lines])])
quarter_report_expressions_by_line = quarter_report_expressions.grouped('report_line_id')
for line, expressions in quarter_report_expressions_by_line.items():
line_dict = next(report_line for report_line in quarter_report_lines if report_line['name'] == line.name)
expressions_by_label = expressions.grouped('label')
debit_expression = expressions_by_label.get('debit')
credit_expression = expressions_by_label.get('credit')
if debit_expression and credit_expression:
debit_value = line_dict['columns'][colname_to_idx['debit']]['no_format']
report_lines_data_per_month[0][f'{debit_expression.report_line_id.code}a'] = f"{debit_value:.2f}".replace(".", ",") if debit_value else False
credit_value = line_dict['columns'][colname_to_idx['credit']]['no_format']
report_lines_data_per_month[0][f'{credit_expression.report_line_id.code}b'] = f"{credit_value:.2f}".replace(".", ",") if credit_value else False
elif (bool(debit_expression) ^ bool(credit_expression)):
value = line_dict['columns'][colname_to_idx[(debit_expression or credit_expression).label]]['no_format']
report_lines_data_per_month[0][line.code] = f"{value:.2f}".replace(".", ",") if value else False
else:
quarter_months = list(date_utils.date_range(*date_utils.get_quarter(options_date_to)))
report_lines_data_per_month = {date.month: {} for date in quarter_months}
for date in quarter_months:
date_from = date
date_to = date_utils.end_of(date, 'month')
at_date_options = report.get_options({
'selected_variant_id': report.id,
'date': {
'date_from': date_from,
'date_to': date_to,
'mode': 'range',
'filter': 'custom',
},
})
monthly_report_lines = report._get_lines(at_date_options)
monthly_report_expressions = self.env['account.report.expression'].search([('report_line_id', 'in', [line['columns'][0]['report_line_id'] for line in monthly_report_lines])])
monthly_report_expressions_by_line = monthly_report_expressions.grouped('report_line_id')
for line, expressions in monthly_report_expressions_by_line.items():
line_dict = next(report_line for report_line in monthly_report_lines if report_line['name'] == line.name)
expressions_by_label = expressions.grouped('label')
debit_expression = expressions_by_label.get('debit')
credit_expression = expressions_by_label.get('credit')
if debit_expression and credit_expression:
debit_value = line_dict['columns'][colname_to_idx['debit']]['no_format']
report_lines_data_per_month[date.month][f'{debit_expression.report_line_id.code}a'] = f"{debit_value:.2f}".replace(".", ",") if debit_value else False
credit_value = line_dict['columns'][colname_to_idx['credit']]['no_format']
report_lines_data_per_month[date.month][f'{credit_expression.report_line_id.code}b'] = f"{credit_value:.2f}".replace(".", ",") if credit_value else False
elif (bool(debit_expression) ^ bool(credit_expression)):
value = line_dict['columns'][colname_to_idx[(debit_expression or credit_expression).label]]['no_format']
report_lines_data_per_month[date.month][line.code] = f"{value:.2f}".replace(".", ",") if value else False
identificativo = self.env['ir.sequence'].next_by_code('l10n_it_reports.identificativo')
if not identificativo:
self.env['ir.sequence'].create({
'name': "IT Periodic VAT XML Export Identificativo",
'code': "l10n_it_reports.identificativo",
'padding': 5,
})
identificativo = self.env['ir.sequence'].next_by_code('l10n_it_reports.identificativo')
return {
"supply_code": "IVP18",
"declarant_fiscal_code": options["declarant_fiscal_code"],
"declarant_role_code": options["declarant_role_code"],
"id_sistema": options["id_sistema"],
"identificativo": identificativo,
"taxpayer_code": company.l10n_it_codice_fiscale,
"tax_year": options_date_to.year,
"vat_number": "".join([char for char in report.get_vat_for_export(options) if char.isdigit()]),
"parent_company_vat_number": options["parent_company_vat_number"],
"last_month": (options_date_to - relativedelta(months=1)).month,
"company_code": options["company_code"],
"intermediary_code": options["intermediary_code"],
"submission_commitment": options["intermediary_code"] and int(options["submission_commitment"]),
"commitment_date": options["intermediary_code"] and fields.Date.from_string(options["commitment_date"]).strftime("%d%m%Y"),
"intermediary_signature": options["intermediary_code"] and 1,
"quarter": date_utils.get_quarter_number(options_date_to) if quarterly else 0,
"monthly_data": {
month: {
"total_active_operations": month_vals["VP2"],
"total_passive_operations": month_vals["VP3"],
"vat_payable": month_vals["VP4"],
"vat_deducted": month_vals["VP5"],
"vat_due": month_vals["VP6a"],
"vat_credit": month_vals["VP6b"],
"previous_debt": month_vals["VP7"],
"previous_period_credit": month_vals["VP8"],
"previous_year_credit": month_vals["VP9"],
"eu_self_payments": month_vals["VP10"],
"tax_credits": month_vals["VP11"],
"due_interests": month_vals["VP12"],
"method": int(options["method"]),
"advance_payment": month_vals["VP13"],
"amount_to_be_paid": month_vals["VP14a"],
"amount_in_credit": month_vals["VP14b"],
"subcontracting": month_vals["xml_subcontracting"] and 1,
"exceptional_events": month_vals["xml_exceptional_events"] and 1,
"extraordinary_operations": month_vals["xml_extraordinary_operations"] and 1,
} for month, month_vals in report_lines_data_per_month.items()
}
}