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

@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account_account
from . import account_journal
from . import account_move
from . import datev
from . import chart_template
from . import ir_actions_report
from . import res_company
from . import template_de_skr03
from . import template_de_skr04

View file

@ -0,0 +1,19 @@
from odoo import models, _
from odoo.exceptions import UserError
class AccountAccount(models.Model):
_inherit = 'account.account'
def write(self, vals):
if (
'code' in vals
and self.env.company.account_fiscal_country_id.code == 'DE'
and any(
self.env.company in a.company_ids and a.code != vals['code']
for a in self
)
):
if self.env['account.move.line'].search_count([('account_id', 'in', self.ids)], limit=1):
raise UserError(_("You can not change the code of an account."))
return super().write(vals)

View file

@ -2,6 +2,7 @@
from odoo import api, models
class AccountJournal(models.Model):
_inherit = "account.journal"

View file

@ -0,0 +1,19 @@
from odoo import models, api, fields
class AccountMove(models.Model):
_inherit = 'account.move'
@api.depends('country_code', 'move_type')
def _compute_show_delivery_date(self):
# EXTENDS 'account'
super()._compute_show_delivery_date()
for move in self:
if move.country_code == 'DE':
move.show_delivery_date = move.is_sale_document()
def _post(self, soft=True):
for move in self:
if move.country_code == 'DE' and move.is_sale_document() and not move.delivery_date:
move.delivery_date = move.invoice_date or fields.Date.context_today(self)
return super()._post(soft)

View file

@ -1,53 +1,24 @@
# -*- coding: utf-8 -*-
from odoo import models, Command, _
from odoo.addons.account.models.chart_template import template
from odoo import models
class AccountChartTemplate(models.Model):
class AccountChartTemplate(models.AbstractModel):
_inherit = 'account.chart.template'
# Write paperformat and report template used on company
def _load(self, company):
res = super(AccountChartTemplate, self)._load(company)
if self in [
self.env.ref('l10n_de_skr03.l10n_de_chart_template', raise_if_not_found=False),
self.env.ref('l10n_de_skr04.l10n_chart_de_skr04', raise_if_not_found=False)
]:
company.write({
'external_report_layout_id': self.env.ref('l10n_din5008.external_layout_din5008').id,
'paperformat_id': self.env.ref('l10n_din5008.paperformat_euro_din').id
})
@template('de_skr03', 'res.company')
@template('de_skr04', 'res.company')
def _get_de_res_company(self):
return {
self.env.company.id: {
'external_report_layout_id': 'l10n_din5008.external_layout_din5008',
'paperformat_id': 'l10n_din5008.paperformat_euro_din',
'restrictive_audit_trail': True,
}
}
outstanding_receipt = company.account_journal_payment_debit_account_id
outstanding_payment = company.account_journal_payment_credit_account_id
asset_tag = self.env.ref('l10n_de.tag_de_asset_bs_B_II_4')
outstanding_receipt['tag_ids'] += asset_tag
outstanding_payment['tag_ids'] += asset_tag
return res
def _prepare_transfer_account_template(self):
res = super(AccountChartTemplate, self)._prepare_transfer_account_template(None)
if self in [
self.env.ref('l10n_de_skr03.l10n_de_chart_template', raise_if_not_found=False),
self.env.ref('l10n_de_skr04.l10n_chart_de_skr04', raise_if_not_found=False)
]:
tag_ids = res.get('tag_ids', [])
tag_ids += [Command.link(self.env.ref('l10n_de.tag_de_asset_bs_B_II_4').id)]
res['tag_ids'] = tag_ids
return res
def _create_liquidity_journal_suspense_account(self, company, code_digits):
if self not in [
self.env.ref('l10n_de_skr03.l10n_de_chart_template', raise_if_not_found=False),
self.env.ref('l10n_de_skr04.l10n_chart_de_skr04', raise_if_not_found=False)
]:
return super()._create_liquidity_journal_suspense_account(company, code_digits)
return self.env['account.account'].create({
'name': _("Bank Suspense Account"),
'code': self.env['account.account']._search_new_account_code(company, code_digits, company.bank_account_code_prefix or ''),
'account_type': 'asset_current',
'company_id': company.id,
'tag_ids': self.env.ref('l10n_de.tag_de_asset_bs_B_IV')
})
def _setup_utility_bank_accounts(self, template_code, company, template_data):
super()._setup_utility_bank_accounts(template_code, company, template_data)
if template_code in ["de_skr03", "de_skr04"]:
company.account_journal_suspense_account_id.tag_ids = self.env.ref('l10n_de.tag_de_asset_bs_B_II_4')
company.transfer_account_id.tag_ids = self.env.ref('l10n_de.tag_de_asset_bs_B_IV')

View file

@ -1,19 +1,10 @@
from odoo import fields, models
class AccountTaxTemplate(models.Model):
_inherit = 'account.tax.template'
l10n_de_datev_code = fields.Char(size=4)
def _get_tax_vals(self, company, tax_template_to_tax):
vals = super(AccountTaxTemplate, self)._get_tax_vals(company, tax_template_to_tax)
vals['l10n_de_datev_code'] = self.l10n_de_datev_code
return vals
class AccountTax(models.Model):
_inherit = "account.tax"
l10n_de_datev_code = fields.Char(size=4, help="4 digits code use by Datev")
l10n_de_datev_code = fields.Char(size=4, help="4 digits code use by Datev", tracking=True)
class ProductTemplate(models.Model):
@ -26,15 +17,21 @@ class ProductTemplate(models.Model):
company = self.env.company
if company.account_fiscal_country_id.code == "DE":
if not self.property_account_income_id:
taxes = self.taxes_id.filtered(lambda t: t.company_id == company)
taxes = self.taxes_id.filtered_domain(self.env['account.tax']._check_company_domain(company))
if not result['income'] or (result['income'].tax_ids and taxes and taxes[0] not in result['income'].tax_ids):
result_income = self.env['account.account'].search([('internal_group', '=', 'income'), ('deprecated', '=', False),
('tax_ids', 'in', taxes.ids)], limit=1)
result_income = self.env['account.account'].with_company(company).search([
*self.env['account.account']._check_company_domain(company),
('internal_group', '=', 'income'),
('tax_ids', 'in', taxes.ids)
], limit=1)
result['income'] = result_income or result['income']
if not self.property_account_expense_id:
supplier_taxes = self.supplier_taxes_id.filtered(lambda t: t.company_id == company)
supplier_taxes = self.supplier_taxes_id.filtered_domain(self.env['account.tax']._check_company_domain(company))
if not result['expense'] or (result['expense'].tax_ids and supplier_taxes and supplier_taxes[0] not in result['expense'].tax_ids):
result_expense = self.env['account.account'].search([('internal_group', '=', 'expense'), ('deprecated', '=', False),
('tax_ids', 'in', supplier_taxes.ids)], limit=1)
result_expense = self.env['account.account'].with_company(company).search([
*self.env['account.account']._check_company_domain(company),
('internal_group', '=', 'expense'),
('tax_ids', 'in', supplier_taxes.ids),
], limit=1)
result['expense'] = result_expense or result['expense']
return result

View file

@ -10,10 +10,30 @@ import stdnum.exceptions
class ResCompany(models.Model):
_inherit = 'res.company'
l10n_de_stnr = fields.Char(string="St.-Nr.", help="Steuernummer. Scheme: ??FF0BBBUUUUP, e.g.: 2893081508152 https://de.wikipedia.org/wiki/Steuernummer")
l10n_de_widnr = fields.Char(string="W-IdNr.", help="Wirtschafts-Identifikationsnummer.")
l10n_de_stnr = fields.Char(
string="St.-Nr.",
help="Tax number. Scheme: ??FF0BBBUUUUP, e.g.: 2893081508152 https://de.wikipedia.org/wiki/Steuernummer",
tracking=True,
)
l10n_de_widnr = fields.Char(string="W-IdNr.", help="Business identification number.", tracking=True)
def write(self, vals):
if (
'account_fiscal_country_id' in vals
and (german_companies := self.filtered(lambda c: c.account_fiscal_country_id.code == 'DE'))
and self.env['res.country'].browse(vals['account_fiscal_country_id']).code != 'DE'
and self.env['account.move'].search_count([('company_id', 'in', german_companies.ids)], limit=1)
):
raise ValidationError(_("You cannot change the fiscal country."))
return super().write(vals)
@api.depends('country_code')
def _compute_force_restrictive_audit_trail(self):
super()._compute_force_restrictive_audit_trail()
for company in self:
company.force_restrictive_audit_trail |= company.country_code == 'DE'
@api.constrains('state_id', 'l10n_de_stnr')
def _validate_l10n_de_stnr(self):
for record in self:

View file

@ -0,0 +1,149 @@
# 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('de_skr03')
def _get_de_skr03_template_data(self):
return {
'code_digits': '4',
'property_account_receivable_id': 'account_1410',
'property_account_payable_id': 'account_1610',
'property_stock_valuation_account_id': 'account_3960',
'name': 'German Chart of Accounts SKR03',
}
@template('de_skr03', 'res.company')
def _get_de_skr03_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.de',
'bank_account_code_prefix': '120',
'cash_account_code_prefix': '100',
'transfer_account_code_prefix': '1360',
'account_default_pos_receivable_account_id': 'account_1411',
'income_currency_exchange_account_id': 'account_2660',
'expense_currency_exchange_account_id': 'account_2150',
'account_journal_early_pay_discount_loss_account_id': 'account_2130',
'account_journal_early_pay_discount_gain_account_id': 'account_2670',
'account_sale_tax_id': 'tax_ust_19_skr03',
'account_purchase_tax_id': 'tax_vst_19_skr03',
'expense_account_id': 'account_3400',
'income_account_id': 'account_8400',
'account_stock_journal_id': 'inventory_valuation',
'account_stock_valuation_id': 'account_7200',
},
}
@template('de_skr03', 'account.reconcile.model')
def _get_de_skr03_reconcile_model(self):
return {
'reconcile_3731': {
'name': 'Discount-EK-7%',
'line_ids': [
Command.create({
'account_id': 'account_3731',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_vst_7_skr03',
]),
],
'amount_string': '100',
'label': 'Discount-EK-7%',
}),
],
},
'reconcile_3736': {
'name': 'Discount-EK-19%',
'line_ids': [
Command.create({
'account_id': 'account_3736',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_vst_19_skr03',
]),
],
'amount_string': '100',
'label': 'Discount-EK-19%',
}),
],
},
'reconcile_8731': {
'name': 'Discount-VK-7%',
'line_ids': [
Command.create({
'account_id': 'account_8731',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_7_skr03',
]),
],
'amount_string': '100',
'label': 'Discount-VK-7%',
}),
],
},
'reconcile_8736': {
'name': 'Discount-VK-19%',
'line_ids': [
Command.create({
'account_id': 'account_8736',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_19_skr03',
]),
],
'amount_string': '100',
'label': 'Discount-VK-19%',
}),
],
},
'reconcile_2401': {
'name': 'Loss of receivables-7%',
'line_ids': [
Command.create({
'account_id': 'account_2401',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_7_skr03',
]),
],
'amount_string': '100',
'label': 'Loss of receivables-7%',
}),
],
},
'reconcile_2406': {
'name': 'Loss of receivables-19%',
'line_ids': [
Command.create({
'account_id': 'account_2406',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_19_skr03',
]),
],
'amount_string': '100',
'label': 'Loss of receivables-19%',
}),
],
},
}
@template('de_skr03', 'account.account')
def _get_de_skr03_account_account(self):
return {
'account_7200': {
'account_stock_expense_id': 'account_3000',
'account_stock_variation_id': 'account_3955',
},
}

View file

@ -0,0 +1,150 @@
# 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('de_skr04')
def _get_de_skr04_template_data(self):
return {
'name': 'German chart of accounts SKR04',
'code_digits': '4',
'property_account_receivable_id': 'chart_skr04_1205',
'property_account_payable_id': 'chart_skr04_3301',
}
@template('de_skr04', 'res.company')
def _get_de_skr04_res_company(self):
return {
self.env.company.id: {
'account_fiscal_country_id': 'base.de',
'bank_account_code_prefix': '180',
'cash_account_code_prefix': '160',
'transfer_account_code_prefix': '1460',
'account_default_pos_receivable_account_id': 'chart_skr04_1206',
'income_currency_exchange_account_id': 'chart_skr04_4840',
'expense_currency_exchange_account_id': 'chart_skr04_6880',
'account_journal_early_pay_discount_loss_account_id': 'chart_skr04_4730',
'account_journal_early_pay_discount_gain_account_id': 'chart_skr04_5730',
'default_cash_difference_income_account_id': 'chart_skr04_9991',
'default_cash_difference_expense_account_id': 'chart_skr04_9994',
'account_sale_tax_id': 'tax_ust_19_skr04',
'account_purchase_tax_id': 'tax_vst_19_skr04',
'expense_account_id': 'chart_skr04_5400',
'income_account_id': 'chart_skr04_4400',
'account_stock_journal_id': 'inventory_valuation',
'account_stock_valuation_id': 'chart_skr04_1000',
},
}
@template('de_skr04', 'account.reconcile.model')
def _get_de_skr04_reconcile_model(self):
return {
'reconcile_5731': {
'name': 'Discount-EK-7%',
'line_ids': [
Command.create({
'account_id': 'chart_skr04_5731',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_vst_7_skr04',
]),
],
'amount_string': '100',
'label': 'Discount-EK-7%',
}),
],
},
'reconcile_5736': {
'name': 'Discount-EK-19%',
'line_ids': [
Command.create({
'account_id': 'chart_skr04_5736',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_vst_19_skr04',
]),
],
'amount_string': '100',
'label': 'Discount-EK-19%',
}),
],
},
'reconcile_4731': {
'name': 'Skonto-VK-7%',
'line_ids': [
Command.create({
'account_id': 'chart_skr04_4731',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_7_skr04',
]),
],
'amount_string': '100',
'label': 'Discount-VK-7%',
}),
],
},
'reconcile_4736': {
'name': 'Discount-VK-19%',
'line_ids': [
Command.create({
'account_id': 'chart_skr04_4736',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_19_skr04',
]),
],
'amount_string': '100',
'label': 'Discount-VK-19%',
}),
],
},
'reconcile_6931': {
'name': 'Loss of receivables-7%',
'line_ids': [
Command.create({
'account_id': 'chart_skr04_6931',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_7_skr04',
]),
],
'amount_string': '100',
'label': 'Loss of receivables-7%',
}),
],
},
'reconcile_6936': {
'name': 'Loss of receivables-19%',
'line_ids': [
Command.create({
'account_id': 'chart_skr04_6936',
'amount_type': 'percentage',
'tax_ids': [
Command.set([
'tax_ust_19_skr04',
]),
],
'amount_string': '100',
'label': 'Loss of receivables-19%',
}),
],
},
}
@template('de_skr04', 'account.account')
def _get_de_skr04_account_account(self):
return {
'chart_skr04_1000': {
'account_stock_expense_id': 'chart_skr04_5000',
'account_stock_variation_id': 'chart_skr04_5880',
},
}