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

122 lines
6.1 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools import SQL
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 == 'NO':
options.setdefault('buttons', []).append({
'name': _('SAF-T'),
'sequence': 50,
'action': 'export_file',
'action_param': 'l10n_no_export_saft_to_xml',
'file_export_type': _('XML')
})
@api.model
def _l10n_no_prepare_saft_report_values(self, report, options):
options['saft_allow_empty_address'] = self.env.company.country_code == 'NO'
template_vals = self._saft_prepare_report_values(report, options)
# The Norwegian version of the SAF-T asks for a standard tax code to be given.
norw_taxes_standard_codes = self.env['account.tax'].browse([tax_vals['id'] for tax_vals in template_vals['tax_vals_list']]).mapped('l10n_no_standard_code')
for tax_vals, standard_code in zip(template_vals['tax_vals_list'], norw_taxes_standard_codes):
if not standard_code:
raise UserError(_("Please set up standard tax codes for your Norwegian taxes."))
tax_vals['standard_code'] = standard_code
# The Norwegian version of the SAF-T requires account code to be provided along with the opening/closing
# credit/debit of customers and suppliers
accounts_by_partners = self._l10n_no_saft_get_partners_accounts(report, options)
for partner_vals in template_vals['customer_vals_list'] + template_vals['supplier_vals_list']:
partner_id = partner_vals['partner'].id
if partner_id in accounts_by_partners:
partner_vals['accounts'] = list(accounts_by_partners[partner_id].values())
template_vals.update({
'xmlns': 'urn:StandardAuditFile-Taxation-Financial:NO',
'file_version': '1.30',
'accounting_basis': 'A',
})
return template_vals
@api.model
def l10n_no_export_saft_to_xml(self, options):
report = self.env['account.report'].browse(options['report_id'])
template_vals = self._l10n_no_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_no_saft.saft_template_inherit_l10n_no_saft', 'file_type': 'xml'},
template_vals['errors'],
)
return file_data
def _saft_get_account_type(self, account):
# OVERRIDE account_saft/models/account_general_ledger
if self.env.company.account_fiscal_country_id.code != 'NO':
return super()._saft_get_account_type(account)
return "GL"
def _l10n_no_saft_get_partners_accounts(self, report, options):
"""Retrieve the accounts used for transactions with the different partners (customer/supplier).
The Norwegian regulation (based on xsd file) requires a list of accounts for every partner, with starting and closing balances.
The partner ledger in Odoo provides starting and closing balance for every partner, but it is account insensitive.
So it is needed to fetch account lines in order to compute all of this, on account/partner basis.
This is based on the Lithuanian method of the same name (next SAF-T needing this might do it in account_saft directly).
:rtype: dict
:return: dictionary of partners' accounts with the account code and its opening/closing balance
"""
date_from = fields.Date.to_date(options['date']['date_from'])
date_to = fields.Date.to_date(options['date']['date_to'])
# Fetch data from beginning
query = report._get_report_query(options, 'from_beginning')
account_alias = query.join(lhs_alias='account_move_line', lhs_column='account_id', rhs_table='account_account', rhs_column='id', link='account_id')
account_code = self.env['account.account']._field_to_sql(account_alias, 'code', query)
account_type = SQL.identifier(account_alias, 'account_type')
# The balance dating from earlier periods are computed as opening
# The balance up to the end of the current period are computed as closing
self.env.cr.execute(SQL(
'''
SELECT DISTINCT
account_move_line.partner_id,
%(account_code)s AS code,
CASE WHEN account_move_line.date < %(date_from)s THEN SUM(account_move_line.balance) ELSE 0 END AS opening_balance,
CASE WHEN account_move_line.date <= %(date_to)s THEN SUM(account_move_line.balance) ELSE 0 END AS closing_balance
FROM %(table_references)s
WHERE %(search_condition)s
AND %(account_type)s IN ('asset_receivable', 'liability_payable')
GROUP BY account_move_line.partner_id, %(account_code)s, account_move_line.date
''',
account_code=account_code,
date_from=date_from,
date_to=date_to,
table_references=query.from_clause,
search_condition=query.where_clause,
account_type=account_type,
))
partners_accounts = {}
for vals in self.env.cr.dictfetchall():
partner_id = vals['partner_id']
account_code = vals['code']
partner_account_code_balances = partners_accounts.setdefault(partner_id, {}).setdefault(account_code, {
'code': account_code,
'opening_balance': 0,
'closing_balance': 0,
})
partner_account_code_balances['opening_balance'] += vals['opening_balance']
partner_account_code_balances['closing_balance'] += vals['closing_balance']
return partners_accounts