# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import fields, models, _ from odoo.exceptions import UserError from odoo.tools import float_compare class L10n_FrReportHandler(models.AbstractModel): _name = 'l10n_fr.report.handler' _inherit = ['account.tax.report.handler'] _description = 'French Report Custom Handler' def _custom_options_initializer(self, report, options, previous_options): super()._custom_options_initializer(report, options, previous_options=previous_options) options['buttons'].append({ 'name': _('EDI VAT'), 'sequence': 30, 'action': 'send_vat_report', }) def send_vat_report(self, options): report = self.env['account.report'].browse(options['report_id']) view_id = self.env.ref('l10n_fr_reports.view_l10n_fr_reports_report_form').id date_from, date_to = report.return_type_ids._get_period_boundaries(self.env.company, fields.Date.to_date(options['date']['date_from'])) account_return = self.env['account.return']._get_return_from_report_options(options) closing_moves = account_return.closing_move_ids if account_return else None if not closing_moves: raise UserError(_("You need to complete the tax closing process for this period before submitting the report to the French administration.")) l10n_fr_vat_report = self.env['l10n_fr_reports.send.vat.report'].create({ 'return_id': account_return.id, 'report_id': report.id, 'date_from': date_from, 'date_to': date_to, }) return { 'name': _('EDI VAT'), 'view_mode': 'form', 'views': [[view_id, 'form']], 'res_model': 'l10n_fr_reports.send.vat.report', 'res_id': l10n_fr_vat_report.id, 'type': 'ir.actions.act_window', 'target': 'new', } def action_audit_cell(self, options, params): # OVERRIDES 'account_reports' # Each line of the French VAT report is rounded to the unit. # In addition, the tax amounts are computed using the rounded base amounts. # The computation of the tax lines is done using the 'aggregation' engine, # so the tax tags are no longer used in the report. # That means the 'expression_label' needs to be adjusted when auditing tax lines, # in order to target the expression that uses the 'tax_tags' engine, # if we want to display the expected journal items. report_line = self.env['account.report.line'].browse(params['report_line_id']) if set(report_line.expression_ids.mapped('label')) == {'balance', 'balance_from_tags'}: params['expression_label'] = 'balance_from_tags' return report_line.report_id.action_audit_cell(options, params) def _customize_warnings(self, report, options, all_column_groups_expression_totals, warnings): def _evaluate_check(check_func): return all( check_func(expression_totals) for expression_totals in all_column_groups_expression_totals.values() ) def _compare_expression_totals(expression_totals): return float_compare(sum( expression_totals[balance_line_expression_per_line_code[code]]['value'] for code in ['box_A1', 'box_A2', 'box_A3', 'box_B2', 'box_B3', 'box_B4'] ), sum( expression_totals[balance_line_expression_per_line_code[code]]['value'] for code in [ 'box_08_base', 'box_09_base', 'box_9B_base', 'box_10_base', 'box_11_base', 'box_T1_base', 'box_T2_base', 'box_T3_base', 'box_T4_base', 'box_T5_base', 'box_T6_base', 'box_T7_base', ] ), 2) == 0 super()._customize_warnings(report, options, all_column_groups_expression_totals, warnings) balance_line_expression_per_line_code = { line.code: line.expression_ids.filtered(lambda x: x.label == 'balance') for line in report.line_ids if line.code } checks = [ ( _('Sum of field 08+09+9B+10+11+T1->T7 is not equal to sum of field A1+A2+A3+B2+B3+B4'), _compare_expression_totals, ) ] failed_controls = [ check_name for check_name, check_func in checks if not _evaluate_check(check_func) ] if failed_controls: warnings['l10n_fr_reports.tax_report_warning_checks'] = {'failed_controls': failed_controls, 'alert_type': 'danger'}