19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:31:16 +01:00
parent 89c6e82fe7
commit 1b82c20a58
572 changed files with 43570 additions and 53303 deletions

View file

@ -1,9 +1,8 @@
# coding: utf-8
# Copyright 2016 Vauxoo (https://www.vauxoo.com) <info@vauxoo.com>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import template_mx
from . import account_account
from . import account_tax
from . import res_bank
from . import res_company
from . import res_config_settings
from . import chart_template
from . import account_move_line

View file

@ -9,9 +9,11 @@ class AccountAccount(models.Model):
# EXTENDS account - ensure there is a tag on created MX accounts
# The computation is a bit naive and might not be correct in all cases.
accounts = super().create(vals_list)
debit_tag = self.env.ref('l10n_mx.tag_debit_balance_account')
credit_tag = self.env.ref('l10n_mx.tag_credit_balance_account')
mx_account_no_tags = accounts.filtered(lambda a: a.company_id.country_code == 'MX' and not a.tag_ids & (credit_tag + debit_tag))
debit_tag = self.env.ref('l10n_mx.tag_debit_balance_account', raise_if_not_found=False)
credit_tag = self.env.ref('l10n_mx.tag_credit_balance_account', raise_if_not_found=False)
if not debit_tag or not credit_tag:
return accounts
mx_account_no_tags = accounts.filtered(lambda a: 'MX' in a.company_ids.mapped('country_code') and not a.tag_ids & (credit_tag + debit_tag))
DEBIT_CODES = ['1', '5', '6', '7'] # all other codes are considered "credit"
for account in mx_account_no_tags:
tag_id = debit_tag.id if account.code[0] in DEBIT_CODES else credit_tag.id

View file

@ -0,0 +1,17 @@
from odoo import models
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
def _compute_account_id(self):
# EXTENDS 'account'
super()._compute_account_id()
for line in self:
if (
line.move_id.country_code == 'MX'
and line.move_id.move_type == 'out_refund'
and line.display_type == 'product'
and line.company_id.l10n_mx_income_return_discount_account_id
):
line.account_id = line.company_id.l10n_mx_income_return_discount_account_id

View file

@ -1,32 +1,11 @@
# coding: utf-8
from odoo import models, fields
class AccountTaxTemplate(models.Model):
_inherit = 'account.tax.template'
l10n_mx_tax_type = fields.Selection(
selection=[
('Tasa', "Tasa"),
('Cuota', "Cuota"),
('Exento', "Exento"),
],
string="Factor Type",
default='Tasa',
help="The CFDI version 3.3 have the attribute 'TipoFactor' in the tax lines. In it is indicated the factor "
"type that is applied to the base of the tax.")
def _get_tax_vals(self, company, tax_template_to_tax):
# OVERRIDE
res = super()._get_tax_vals(company, tax_template_to_tax)
res['l10n_mx_tax_type'] = self.l10n_mx_tax_type
return res
from odoo import models, fields, api
class AccountTax(models.Model):
_inherit = 'account.tax'
l10n_mx_tax_type = fields.Selection(
l10n_mx_factor_type = fields.Selection(
selection=[
('Tasa', "Tasa"),
('Cuota', "Cuota"),
@ -34,5 +13,38 @@ class AccountTax(models.Model):
],
string="Factor Type",
default='Tasa',
help="The CFDI version 3.3 have the attribute 'TipoFactor' in the tax lines. In it is indicated the factor "
"type that is applied to the base of the tax.")
help="Mexico: 'TipoFactor' is an attribute for CFDI 4.0. This indicates the factor type that is applied to the base of the tax.",
)
l10n_mx_tax_type = fields.Selection(
selection=[
('isr', "ISR"),
('iva', "IVA"),
('ieps', "IEPS"),
('local', "Local"),
],
string="SAT Tax Type",
compute="_compute_l10n_mx_tax_type",
store=True,
readonly=False,
)
@api.depends("country_id")
def _compute_l10n_mx_tax_type(self):
for tax in self:
tax.l10n_mx_tax_type = 'iva' if tax.country_id.code == 'MX' else False
@api.model
def _round_tax_details_tax_amounts(self, base_lines, company, mode='mixed'):
# EXTENDS 'account'
country_code = company.account_fiscal_country_id.code
if country_code == 'MX':
mode = 'excluded'
super()._round_tax_details_tax_amounts(base_lines, company, mode=mode)
@api.model
def _round_tax_details_base_lines(self, base_lines, company, mode='mixed'):
# EXTENDS 'account'
country_code = company.account_fiscal_country_id.code
if country_code == 'MX':
mode = 'excluded'
super()._round_tax_details_base_lines(base_lines, company, mode=mode)

View file

@ -1,49 +0,0 @@
# coding: utf-8
# Copyright 2016 Vauxoo (https://www.vauxoo.com) <info@vauxoo.com>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from odoo import models, api, _
class AccountChartTemplate(models.Model):
_inherit = "account.chart.template"
def _load(self, company):
res = super()._load(company)
if company.chart_template_id == self.env.ref('l10n_mx.mx_coa'):
company.write({
'account_sale_tax_id': self.env.ref(f'l10n_mx.{company.id}_tax12'),
'account_purchase_tax_id': self.env.ref(f'l10n_mx.{company.id}_tax14'),
})
return res
@api.model
def generate_journals(self, acc_template_ref, company, journals_dict=None):
"""Set the tax_cash_basis_journal_id on the company"""
res = super(AccountChartTemplate, self).generate_journals(
acc_template_ref, company, journals_dict=journals_dict)
if not self == self.env.ref('l10n_mx.mx_coa'):
return res
journal_basis = self.env['account.journal'].search([
('company_id', '=', company.id),
('type', '=', 'general'),
('code', '=', 'CBMX')], limit=1)
company.write({'tax_cash_basis_journal_id': journal_basis.id})
return res
def _prepare_all_journals(self, acc_template_ref, company, journals_dict=None):
"""Create the tax_cash_basis_journal_id"""
res = super(AccountChartTemplate, self)._prepare_all_journals(
acc_template_ref, company, journals_dict=journals_dict)
if not self == self.env.ref('l10n_mx.mx_coa'):
return res
account = acc_template_ref.get(self.env.ref('l10n_mx.cuenta118_01').id)
res.append({
'type': 'general',
'name': _('Effectively Paid'),
'code': 'CBMX',
'company_id': company.id,
'default_account_id': account,
'show_on_dashboard': True,
})
return res

View file

@ -4,18 +4,26 @@
from odoo import fields, models
class Bank(models.Model):
class ResBank(models.Model):
_inherit = "res.bank"
def _get_fiscal_country_codes(self):
return ','.join(self.env.companies.mapped('account_fiscal_country_id.code'))
l10n_mx_edi_code = fields.Char(
"ABM Code",
help="Three-digit number assigned by the ABM to identify banking "
"institutions (ABM is an acronym for Asociación de Bancos de México)")
fiscal_country_codes = fields.Char(store=False, default=_get_fiscal_country_codes)
class ResPartnerBank(models.Model):
_inherit = "res.partner.bank"
def _get_fiscal_country_codes(self):
return ','.join(self.env.companies.mapped('account_fiscal_country_id.code'))
l10n_mx_edi_clabe = fields.Char(
"CLABE", help="Standardized banking cipher for Mexico. More info "
"wikipedia.org/wiki/CLABE")
fiscal_country_codes = fields.Char(store=False, default=_get_fiscal_country_codes)

View file

@ -0,0 +1,16 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
l10n_mx_income_return_discount_account_id = fields.Many2one(
comodel_name='account.account',
string='Income account for returns and discounts'
)
l10n_mx_income_re_invoicing_account_id = fields.Many2one(
comodel_name='account.account',
string='Income account for re-invoicing'
)

View file

@ -1,9 +1,15 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
from odoo import models, fields
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
module_l10n_mx_edi = fields.Boolean('Mexican Electronic Invoicing')
l10n_mx_account_income_return_discount_id = fields.Many2one(
comodel_name="account.account",
string='Income Returns and Discounts Account',
readonly=False,
related='company_id.l10n_mx_income_return_discount_account_id',
domain="[('account_type', '=', 'income')]",
)

View file

@ -0,0 +1,86 @@
# 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('mx')
def _get_mx_template_data(self):
return {
'code_digits': '9',
'display_invoice_amount_total_words': True,
'property_account_receivable_id': 'cuenta105_01',
'property_account_payable_id': 'cuenta201_01',
'property_stock_valuation_account_id': 'cuenta115_01',
'property_cash_basis_base_account_id': 'cuenta801_01_99',
}
@template('mx', 'res.company')
def _get_mx_res_company(self):
return {
self.env.company.id: {
'anglo_saxon_accounting': True,
'account_fiscal_country_id': 'base.mx',
'bank_account_code_prefix': '102.01.0',
'cash_account_code_prefix': '101.01.0',
'transfer_account_code_prefix': '102.01.01',
'account_default_pos_receivable_account_id': 'cuenta105_02',
'income_currency_exchange_account_id': 'cuenta702_01',
'expense_currency_exchange_account_id': 'cuenta701_01',
'deferred_expense_account_id': 'cuenta173_01',
'account_journal_early_pay_discount_loss_account_id': 'cuenta402_01',
'account_journal_early_pay_discount_gain_account_id': 'cuenta503_01',
'tax_cash_basis_journal_id': 'cbmx',
'account_sale_tax_id': 'tax12',
'account_purchase_tax_id': 'tax14',
'expense_account_id': 'cuenta601_84',
'income_account_id': 'cuenta401_01',
'account_cash_basis_base_account_id': 'cuenta801_01_99',
'l10n_mx_income_return_discount_account_id': 'cuenta402_01',
'l10n_mx_income_re_invoicing_account_id': 'cuenta402_04',
'account_stock_journal_id': 'inventory_valuation',
'account_stock_valuation_id': 'cuenta115_01',
},
}
@template('mx', 'account.journal')
def _get_mx_account_journal(self):
return {
"cbmx": {
'type': 'general',
'name': _('Effectively Paid'),
'code': 'CBMX',
'default_account_id': "cuenta118_01",
'show_on_dashboard': True,
},
'cash': {
'name': _("Cash"),
'type': 'cash',
},
}
def _get_accounts_data_values(self, company, template_data, bank_prefix='', code_digits=0):
accounts_data = super()._get_accounts_data_values(company, template_data, bank_prefix=bank_prefix, code_digits=code_digits)
if company.account_fiscal_country_id.code == 'MX':
accounts_data.update({
'default_cash_difference_income_account_id': {
'name': _('Other Income'),
'code': '403.01.01'
},
'default_cash_difference_expense_account_id': {
'name': 'Cash Difference Loss',
'code': '601.84.02',
}
})
return accounts_data
@template('mx', 'account.account')
def _get_mx_account_account(self):
return {
'cuenta115_01': {
'account_stock_expense_id': 'cuenta505_01',
'account_stock_variation_id': 'cuenta501_02',
},
}