19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:31:28 +01:00
parent ff721d030e
commit 7721452493
1826 changed files with 124775 additions and 274114 deletions

View file

@ -0,0 +1,17 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account_move
from . import account_tax
from . import res_company
from . import res_config_settings
from . import res_partner
from . import template_es_assec
from . import template_es_canary_assoc
from . import template_es_canary_common
from . import template_es_canary_full
from . import template_es_canary_pymes
from . import template_es_common
from . import template_es_common_mainland
from . import template_es_coop_full
from . import template_es_coop_pymes
from . import template_es_full
from . import template_es_pymes

View file

@ -0,0 +1,31 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, fields, api
class AccountMove(models.Model):
_inherit = 'account.move'
l10n_es_is_simplified = fields.Boolean("Is Simplified",
compute="_compute_l10n_es_is_simplified", readonly=False, store=True)
# Note: We depend on 'line_ids.balance' instead of 'amount_total_signed' directly.
# Otherwise the field is recomputed when the 'state' changes (since 'amount_total_signed' depends on it);
# the recomputation would i.e. happen when confirming the invoice and override any manual edits of the field.
@api.depends('partner_id', 'line_ids.balance')
def _compute_l10n_es_is_simplified(self):
simplified_partner = self.env.ref('l10n_es.partner_simplified', raise_if_not_found=False)
for move in self:
currency_id = move.currency_id or move.company_id.currency_id
move.l10n_es_is_simplified = (move.country_code == 'ES') and (
(not move.partner_id and move.move_type in ('in_receipt', 'out_receipt'))
or (simplified_partner and move.partner_id == simplified_partner)
or (move.move_type in ('out_invoice', 'out_refund')
and not move.commercial_partner_id.vat
and currency_id.compare_amounts(abs(move.amount_total_signed), move.company_id.l10n_es_simplified_invoice_limit) <= 0
and move.commercial_partner_id.country_id in self.env.ref('base.europe').country_ids
)
)
def _l10n_es_is_dua(self):
self.ensure_one()
return any(t.l10n_es_type == 'dua' for t in self.invoice_line_ids.tax_ids.flatten_taxes_hierarchy())

View file

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class AccountTax(models.Model):
_inherit = 'account.tax'
l10n_es_exempt_reason = fields.Selection(
selection=[
('E1', 'Art. 20'),
('E2', 'Art. 21'),
('E3', 'Art. 22'),
('E4', 'Art. 23 y 24'),
('E5', 'Art. 25'),
('E6', 'Otros'),
],
string="Exempt Reason (Spain)",
)
l10n_es_type = fields.Selection(
selection=[
('exento', 'Exento'),
('sujeto', 'Sujeto'),
('sujeto_agricultura', 'Sujeto Agricultura'),
('sujeto_isp', 'Sujeto ISP'),
('no_sujeto', 'No Sujeto'),
('no_sujeto_loc', 'No Sujeto por reglas de Localization'),
('no_deducible', 'No Deducible'),
('retencion', 'Retencion'),
('recargo', 'Recargo de Equivalencia'),
('dua', 'DUA'),
('ignore', 'Ignore even the base amount'),
],
string="Tax Type (Spain)", default='sujeto'
)
l10n_es_bien_inversion = fields.Boolean('Bien de Inversion', default=False)
# -------------------------------------------------------------------------
# EDI HELPERS
# -------------------------------------------------------------------------
def _l10n_es_get_regime_code(self):
# Regime codes (ClaveRegimenEspecialOTrascendencia)
# NOTE there's 11 more codes to implement, also there can be up to 3 in total
# See https://www.gipuzkoa.eus/documents/2456431/13761128/Anexo+I.pdf/2ab0116c-25b4-f16a-440e-c299952d683d
oss_tag = self.env.ref('l10n_eu_oss.tag_oss', raise_if_not_found=False)
# If there's an OSS tax, it is considered an OSS operation
if oss_tag and oss_tag in self.invoice_repartition_line_ids.tag_ids:
return '17'
if self.filtered(lambda t: t.l10n_es_exempt_reason == 'E2'):
return '02'
return '01'
@api.model
def _l10n_es_get_sujeto_tax_types(self):
return ['sujeto', 'sujeto_isp', 'sujeto_agricultura']
@api.model
def _l10n_es_get_main_tax_types(self):
return {'exento', 'sujeto', 'sujeto_agricultura', 'sujeto_isp', 'no_sujeto', 'no_sujeto_loc', 'no_deducible'}

View file

@ -0,0 +1,11 @@
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
l10n_es_simplified_invoice_limit = fields.Float(
string="Simplified Invoice limit amount",
help="Over this amount is not legally possible to create a simplified invoice",
default=400,
)

View file

@ -0,0 +1,10 @@
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
l10n_es_simplified_invoice_limit = fields.Float(
related='company_id.l10n_es_simplified_invoice_limit',
readonly=False,
)

View file

@ -0,0 +1,37 @@
from odoo import models
class ResPartner(models.Model):
_inherit = 'res.partner'
def _l10n_es_is_foreign(self):
self.ensure_one()
return self.country_id.code not in ('ES', False) or (self.vat or '').startswith("ESN")
def _l10n_es_edi_get_partner_info(self):
""" Used in SII and Veri*factu"""
self.ensure_one()
eu_country_codes = set(self.env.ref('base.europe').country_ids.mapped('code'))
partner_info = {}
IDOtro_ID = self.vat or 'NO_DISPONIBLE'
if (not self.country_id or self.country_id.code == 'ES') and self.vat:
# ES partner with VAT.
partner_info['NIF'] = self.vat.removeprefix('ES')
if self.env.context.get('error_1117'):
partner_info['IDOtro'] = {'IDType': '07', 'ID': IDOtro_ID}
elif self.country_id.code in eu_country_codes and self.vat:
# European partner.
partner_info['IDOtro'] = {'IDType': '02', 'ID': IDOtro_ID}
else:
partner_info['IDOtro'] = {'ID': IDOtro_ID}
if self.vat:
partner_info['IDOtro']['IDType'] = '04'
else:
partner_info['IDOtro']['IDType'] = '06'
if self.country_id:
partner_info['IDOtro']['CodigoPais'] = self.country_id.code
return partner_info

View file

@ -0,0 +1,27 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_assec')
def _get_es_assec_template_data(self):
return {
'name': _('Non-profit entities (2008)'),
'parent': 'es_common_mainland',
}
@template('es_assec', 'res.company')
def _get_es_assec_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '57299',
'account_sale_tax_id': 'account_tax_template_s_iva21b',
'account_purchase_tax_id': 'account_tax_template_p_iva21_bc',
},
}

View file

@ -0,0 +1,43 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_canary_assoc')
def _get_es_canary_assoc_template_data(self):
return {
'name': _('Canary Islands - PGCE non-profit entities (2008)'),
'parent': 'es_canary_common',
}
@template('es_canary_assoc', 'res.company')
def _get_es_canary_assoc_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '572999',
},
}
@template('es_canary_assoc', 'account.account')
def _get_es_canary_assoc_account_account(self):
res = self._parse_csv('es_assec', 'account.account', module='l10n_es')
# Voluntarily remove the `tax_ids` since those are defined for the mainland and not the canaries
for data in res.values():
if 'tax_ids' in data:
del data['tax_ids']
return res
@template('es_canary_assoc', 'account.asset')
def _get_es_canary_assoc_account_asset(self):
# account_asset is not auto-installed when l10n_es is installed
if 'account.asset' not in self.env:
return {}
return self._parse_csv('es_assec', 'account.asset', module='l10n_es')

View file

@ -0,0 +1,28 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_canary_common')
def _get_es_canary_common_template_data(self):
return {
'name': 'Common Canary Islands',
'visible': 0,
'parent': 'es_common',
}
@template('es_canary_common', 'res.company')
def _get_es_canary_common_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '572999',
'account_sale_tax_id': 'account_tax_template_igic_r_7',
'account_purchase_tax_id': 'account_tax_template_igic_sop_7',
},
}

View file

@ -0,0 +1,43 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_canary_full')
def _get_es_canary_full_template_data(self):
return {
'name': _('Canary Islands - Complete (2008)'),
'parent': 'es_canary_common',
}
@template('es_canary_full', 'res.company')
def _get_es_canary_full_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '572999',
},
}
@template('es_canary_full', 'account.account')
def _get_es_canary_full_account_account(self):
res = self._parse_csv('es_full', 'account.account', module='l10n_es')
# Voluntarily remove the `tax_ids` since those are defined for the mainland and not the canaries
for data in res.values():
if 'tax_ids' in data:
del data['tax_ids']
return res
@template('es_canary_full', 'account.asset')
def _get_es_canary_full_account_asset(self):
# account_asset is not auto-installed when l10n_es is installed
if 'account.asset' not in self.env:
return {}
return self._parse_csv('es_full', 'account.asset', module='l10n_es')

View file

@ -0,0 +1,43 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_canary_pymes')
def _get_es_canary_pymes_template_data(self):
return {
'name': _('Canary Islands - SMEs (2008)'),
'parent': 'es_canary_common',
}
@template('es_canary_pymes', 'res.company')
def _get_es_canary_pymes_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '572999',
},
}
@template('es_canary_pymes', 'account.account')
def _get_es_canary_pymes_account_account(self):
res = self._parse_csv('es_pymes', 'account.account', module='l10n_es')
# Voluntarily remove the `tax_ids` since those are defined for the mainland and not the canaries
for data in res.values():
if 'tax_ids' in data:
del data['tax_ids']
return res
@template('es_canary_pymes', 'account.asset')
def _get_es_canary_pymes_account_asset(self):
# account_asset is not auto-installed when l10n_es is installed
if 'account.asset' not in self.env:
return {}
return self._parse_csv('es_pymes', 'account.asset', module='l10n_es')

View file

@ -0,0 +1,50 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_common')
def _get_es_common_template_data(self):
return {
'name': _('Common'),
'visible': 0,
'property_account_receivable_id': 'account_common_4300',
'property_account_payable_id': 'account_common_4100',
}
@template('es_common', 'res.company')
def _get_es_common_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '57299',
'account_default_pos_receivable_account_id': 'account_common_4301',
'income_currency_exchange_account_id': 'account_common_768',
'expense_currency_exchange_account_id': 'account_common_668',
'account_journal_suspense_account_id': 'account_common_572998',
'account_journal_early_pay_discount_loss_account_id': 'account_common_6060',
'account_journal_early_pay_discount_gain_account_id': 'account_common_7060',
'default_cash_difference_income_account_id': 'account_common_778',
'default_cash_difference_expense_account_id': 'account_common_678',
'deferred_expense_account_id': 'account_common_480',
'deferred_revenue_account_id': 'account_common_485',
'expense_account_id': 'account_common_600',
'income_account_id': 'account_common_7000',
'account_stock_journal_id': 'inventory_valuation',
'account_stock_valuation_id': 'account_common_310',
},
}
@template('es_common', 'account.account')
def _get_es_common_account_account(self):
return {
'account_common_310': {
'account_stock_expense_id': 'account_common_601',
'account_stock_variation_id': 'account_common_611',
},
}

View file

@ -0,0 +1,31 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, Command
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_common_mainland')
def _get_es_common_mainland_template_data(self):
return {
'name': 'Common Mainland',
'visible': 0,
'parent': 'es_common',
}
@template('es_common_mainland', 'res.company')
def _get_es_common_mainland_res_company(self):
return {
self.env.company.id: {
'account_sale_tax_id': 'account_tax_template_s_iva21b',
'account_purchase_tax_id': 'account_tax_template_p_iva21_bc',
},
}
@template('es_common_mainland', model='product.product')
def _get_product(self):
return {
'l10n_es.product_dua_valuation_4': {'supplier_taxes_id': [Command.set(['account_tax_template_p_iva4_ibc_group'])]},
'l10n_es.product_dua_valuation_10': {'supplier_taxes_id': [Command.set(['account_tax_template_p_iva10_ibc_group'])]},
'l10n_es.product_dua_valuation_21': {'supplier_taxes_id': [Command.set(['account_tax_template_p_iva21_ibc_group'])]},
}

View file

@ -0,0 +1,26 @@
from odoo import _, models
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_coop_full')
def _get_es_coop_full_template_data(self):
return {
'name': _('Cooperatives - Complete (2008)'),
'parent': 'es_coop_pymes',
}
@template('es_coop_full', 'res.company')
def _get_es_coop_full_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '57299',
'account_sale_tax_id': 'account_tax_template_s_iva21b',
'account_purchase_tax_id': 'account_tax_template_p_iva21_bc',
},
}

View file

@ -0,0 +1,26 @@
from odoo import _, models
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_coop_pymes')
def _get_es_coop_pymes_template_data(self):
return {
'name': _('Cooperatives - SMEs (2008)'),
'parent': 'es_common_mainland',
}
@template('es_coop_pymes', 'res.company')
def _get_es_coop_pymes_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '57299',
'account_sale_tax_id': 'account_tax_template_s_iva21b',
'account_purchase_tax_id': 'account_tax_template_p_iva21_bc',
},
}

View file

@ -0,0 +1,27 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_full')
def _get_es_full_template_data(self):
return {
'name': _('Complete (2008)'),
'parent': 'es_common_mainland',
}
@template('es_full', 'res.company')
def _get_es_full_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '57299',
'account_sale_tax_id': 'account_tax_template_s_iva21b',
'account_purchase_tax_id': 'account_tax_template_p_iva21_bc',
},
}

View file

@ -0,0 +1,28 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, _
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
@template('es_pymes')
def _get_es_pymes_template_data(self):
return {
'name': _('SMEs (2008)'),
'parent': 'es_common_mainland',
'sequence': 0,
}
@template('es_pymes', 'res.company')
def _get_es_pymes_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.es',
'bank_account_code_prefix': '572',
'cash_account_code_prefix': '570',
'transfer_account_code_prefix': '57299',
'account_sale_tax_id': 'account_tax_template_s_iva21b',
'account_purchase_tax_id': 'account_tax_template_p_iva21_bc',
},
}