Files
enterprise-addons/l10n_lu_reports/models/account_general_ledger.py
T

190 lines
9.1 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from itertools import groupby
from odoo.tools import get_lang, SQL
from odoo import api, models, _
class AccountGeneralLedgerReportHandler(models.AbstractModel):
_inherit = 'account.general.ledger.report.handler'
def _custom_options_initializer(self, report, options, previous_options):
super()._custom_options_initializer(report, options, previous_options)
if self.env.company.account_fiscal_country_id.code == 'LU':
options.setdefault('buttons', []).append({
'name': _('FAIA'),
'sequence': 50,
'action': 'export_file',
'action_param': 'l10n_lu_export_saft_to_xml',
'file_export_type': _('XML'),
'branch_allowed': True,
})
@api.model
def _fill_l10n_lu_saft_report_invoices_values(self, options, values):
def get_product_action(message, product_ids, level='warning'):
return {
'message': message,
'action_text': _('View Products'),
'action': self.env['product.product'].browse(product_ids)._get_records_action(name=_("Invalid Products")),
'level': level,
}
def _get_product_vals_list(values, encountered_product_ids):
product_template_name = self.env['product.template']._field_to_sql('product_template', 'name')
uom_name = self.env['uom.uom']._field_to_sql('uom', 'name')
base_uom_name = self.env['uom.uom']._field_to_sql('base_uom', 'name')
self.env.cr.execute(SQL(
'''
SELECT
product.id,
product.barcode,
%(product_template_name)s AS name,
product.product_tmpl_id,
product.default_code,
product_category.name AS product_category,
%(uom_name)s AS standard_uom,
TRUNC(CAST(uom.factor AS NUMERIC), 8) AS uom_ratio,
CASE
WHEN uom.factor != 0
THEN TRUNC(CAST(1.0 / uom.factor AS NUMERIC), 8)
ELSE 0
END AS ratio
FROM product_product product
LEFT JOIN product_template ON product_template.id = product.product_tmpl_id
LEFT JOIN product_category ON product_category.id = product_template.categ_id
LEFT JOIN uom_uom uom ON uom.id = product_template.uom_id
WHERE product.id in %(encountered_product_ids)s
ORDER BY default_code
''',
product_template_name=product_template_name,
uom_name=uom_name,
base_uom_name=base_uom_name,
encountered_product_ids=tuple(encountered_product_ids)
))
product_vals_list = self.env.cr.dictfetchall()
duplicate_product_ids = set()
empty_product_ids = set()
for product_code, grouped_products in groupby(product_vals_list, key=lambda product: product['default_code']):
product_list = list(grouped_products)
if not product_code:
empty_product_ids.update(product_list_item['id'] for product_list_item in product_list)
elif len(product_list) > 1:
for product in product_list:
duplicate_product_ids.add(product['id'])
if duplicate_product_ids:
values['errors']['product_duplicate_ref'] = get_product_action(
_("Some products have duplicate 'Internal Reference', please make them unique."),
list(duplicate_product_ids),
level='danger'
)
if empty_product_ids:
values['errors']['product_missing_ref'] = get_product_action(
_("Some products are missing `Internal Reference`, please define them."),
list(empty_product_ids),
level='danger'
)
return product_vals_list
res = {
'total_invoices_debit': 0.0,
'total_invoices_credit': 0.0,
'total_bills_debit': 0.0,
'total_bills_credit': 0.0,
'invoice_vals_list': [],
'uoms': [],
'product_vals_list': [],
}
# Fill 'total_invoices_debit', 'total_invoices_credit', 'total_bills_debit', 'total_bills_credit', 'invoice_vals_list'.
encountered_product_ids = set()
encountered_product_uom_ids = set()
# TODO: to remove in master, do not include the in_invoice if the template was not updated
template_tree = self.env['ir.qweb']._get_template('l10n_lu_reports.saft_template_inherit_l10n_lu_saft')[0]
missing_tree_node = template_tree.findall('.//PurchaseInvoices')
for move_vals in values['move_vals_list']:
if move_vals['type'] not in ('out_invoice', 'out_refund', 'in_invoice', 'in_refund'):
continue
# TODO: to remove in master, do not include the in_invoice if the template was not updated
if not missing_tree_node and move_vals['type'] not in ('out_invoice', 'out_refund'):
continue
move_vals.update({
'invoice_line_vals_list': [],
'tax_detail_vals_list': [],
'total_invoice_untaxed_balance': 0.0,
'total_invoice_tax_balance': 0.0,
})
for line_vals in move_vals['line_vals_list']:
if line_vals['tax_line_id']:
move_vals['tax_detail_vals_list'].append({
'currency_id': line_vals['currency_id'],
'currency_code': line_vals['currency_code'],
'tax_id': line_vals['tax_line_id'],
'tax_name': line_vals['tax_name'],
'tax_amount': line_vals['tax_amount'],
'tax_base_amount': line_vals['tax_base_amount'],
'tax_amount_type': line_vals['tax_amount_type'],
'amount': line_vals['balance'],
'amount_currency': line_vals['amount_currency'],
'rate': line_vals['rate'],
})
move_vals['total_invoice_tax_balance'] -= line_vals['balance']
elif not line_vals['account_type'] in ('asset_receivable', 'liability_payable') and line_vals['display_type'] == 'product':
move_vals['total_invoice_untaxed_balance'] -= line_vals['balance']
if line_vals['balance'] > 0.0:
total_debit_key = 'total_invoices_debit' if move_vals['type'] in ('out_invoice', 'out_refund') else 'total_bills_debit'
res[total_debit_key] += line_vals['balance']
else:
total_credit_key = 'total_invoices_credit' if move_vals['type'] in ('out_invoice', 'out_refund') else 'total_bills_credit'
res[total_credit_key] -= line_vals['balance']
if line_vals['product_id']:
encountered_product_ids.add(line_vals['product_id'])
if line_vals['product_uom_id']:
encountered_product_uom_ids.add(line_vals['product_uom_id'])
move_vals['invoice_line_vals_list'].append(line_vals)
res['invoice_vals_list'].append(move_vals)
move_vals['total_invoice_balance'] = move_vals['total_invoice_untaxed_balance'] + move_vals['total_invoice_tax_balance']
# Fill 'uoms'.
uoms = self.env['uom.uom'].browse(list(encountered_product_uom_ids))
res['uoms'] = uoms
# Fill 'product_vals_list'.
if len(encountered_product_ids) > 0:
res['product_vals_list'] = _get_product_vals_list(values, encountered_product_ids)
values.update(res)
@api.model
def _l10n_lu_prepare_saft_report_values(self, report, options):
template_vals = self._saft_prepare_report_values(report, options)
template_vals.update({
'xmlns': 'urn:OECD:StandardAuditFile-Taxation/2.00',
'file_version': '2.01',
'accounting_basis': 'Invoice Accounting',
})
self._fill_l10n_lu_saft_report_invoices_values(options, template_vals)
return template_vals
@api.model
def l10n_lu_export_saft_to_xml(self, options):
report = self.env['account.report'].browse(options['report_id'])
template_vals = self._l10n_lu_prepare_saft_report_values(report, options)
file_data = report._generate_file_data_with_error_check(
options,
self.env['ir.qweb']._render,
{'values': template_vals, 'template': 'l10n_lu_reports.saft_template_inherit_l10n_lu_saft', 'file_type': 'xml'},
template_vals['errors'],
)
return file_data