Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 40 additions & 15 deletions l10n_ar_demo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
old_load_manifest = module.load_manifest


def load_manifest(module, mod_path=None):
info = old_load_manifest(module, mod_path=mod_path)
if module in ['l10n_ar', 'l10n_ar_edi', 'l10n_ar_website_sale']:
def load_manifest(module_name, mod_path=None):
info = old_load_manifest(module_name, mod_path=mod_path)
if module_name in ['l10n_ar', 'l10n_ar_edi', 'l10n_ar_website_sale']:
info['demo'] = []
return info

Expand All @@ -26,16 +26,41 @@ def load_manifest(module, mod_path=None):


def _load_l10n_ar_demo_data(cr):
"""
Carga los datos demo de l10n_ar que fueron ocultados por load_manifest.
Este hook se ejecuta antes de cargar los demos de l10n_ar_demo para asegurar
que las dependencias (journals, productos, partners, etc) existan.
"""
env = api.Environment(cr, SUPERUSER_ID, {})
for module_name in ['l10n_ar', 'l10n_ar_edi', 'l10n_ar_website_sale']:
_logger.info('Loading demo data from %s' % module_name)
manifest_file = module.module_manifest(module.get_module_path(module_name))
f = tools.file_open(manifest_file, mode='rb')
try:
info = ast.literal_eval(tools.pycompat.to_text(f.read()))
finally:
f.close()
for demo_data in info.get('demo'):
_logger.info('Loading %s', (demo_data))
tools.convert_file(cr, module_name, demo_data, {}, 'init', True, 'demo', None)
env.cr.commit()

# Verificar si los datos demo ya fueron cargados (para evitar recargas en upgrades)
# Verificamos con company_exento que se crea en el primer archivo demo (exento_demo.xml)
if env['ir.model.data'].search([('module', '=', 'l10n_ar'), ('name', '=', 'company_exento')], limit=1):
_logger.info('Demo data from l10n_ar already loaded, skipping manual load')
return

# Desactivar constraints problemáticas temporalmente durante la carga inicial
# Esto es necesario porque los archivos demo de l10n_ar tienen problemas de orden
AccountJournal = env.registry['account.journal']
orig_check1 = AccountJournal.check_use_document
orig_check2 = AccountJournal._check_afip_configurations
AccountJournal.check_use_document = lambda self: None
AccountJournal._check_afip_configurations = lambda self: None

try:
for module_name in ['l10n_ar', 'l10n_ar_edi', 'l10n_ar_website_sale']:
_logger.info('Loading demo data from %s' % module_name)
manifest_file = module.module_manifest(module.get_module_path(module_name))
f = tools.file_open(manifest_file, mode='rb')
try:
info = ast.literal_eval(tools.pycompat.to_text(f.read()))
finally:
f.close()
for demo_data in info.get('demo', []):
_logger.info('Loading %s', (demo_data))
Comment on lines +59 to +60
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

El uso de .get('demo', []) con valor por defecto [] es más seguro que .get('demo'), ya que evita errores si el manifest no contiene la clave 'demo'. Sin embargo, sería útil añadir un log de advertencia cuando no existan datos demo para cargar, para facilitar el debugging:

demo_files = info.get('demo', [])
if not demo_files:
    _logger.warning('No demo files found for %s', module_name)
    continue
for demo_data in demo_files:
    _logger.info('Loading %s', demo_data)
    tools.convert_file(cr, module_name, demo_data, {}, 'init', True, 'demo', None)
Suggested change
for demo_data in info.get('demo', []):
_logger.info('Loading %s', (demo_data))
demo_files = info.get('demo', [])
if not demo_files:
_logger.warning('No demo files found for %s', module_name)
continue
for demo_data in demo_files:
_logger.info('Loading %s', demo_data)

Copilot uses AI. Check for mistakes.
tools.convert_file(cr, module_name, demo_data, {}, 'init', True, 'demo', None)
env.cr.commit()
finally:
# Restaurar constraints
AccountJournal.check_use_document = orig_check1
AccountJournal._check_afip_configurations = orig_check2
Comment on lines +42 to +66
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La desactivación temporal de constraints mediante la modificación directa de métodos del registro (env.registry['account.journal']) es peligrosa y puede causar problemas de concurrencia en entornos multi-hilo. Si ocurre un error entre las líneas 44-48 y 64-66, las constraints quedarán desactivadas permanentemente. Además, esta técnica modifica el modelo a nivel de clase, afectando a todas las instancias y transacciones en curso, no solo a la transacción actual.

Considere alternativas más seguras como:

  1. Usar env.cr.savepoint() para manejar errores transaccionales
  2. Verificar si existe una forma de cargar datos con validaciones relajadas a través de parámetros de contexto
  3. Si es imprescindible deshabilitar temporalmente las validaciones, documentar claramente los riesgos y añadir protección adicional (por ejemplo, bloqueos de transacción)
Suggested change
# Desactivar constraints problemáticas temporalmente durante la carga inicial
# Esto es necesario porque los archivos demo de l10n_ar tienen problemas de orden
AccountJournal = env.registry['account.journal']
orig_check1 = AccountJournal.check_use_document
orig_check2 = AccountJournal._check_afip_configurations
AccountJournal.check_use_document = lambda self: None
AccountJournal._check_afip_configurations = lambda self: None
try:
for module_name in ['l10n_ar', 'l10n_ar_edi', 'l10n_ar_website_sale']:
_logger.info('Loading demo data from %s' % module_name)
manifest_file = module.module_manifest(module.get_module_path(module_name))
f = tools.file_open(manifest_file, mode='rb')
try:
info = ast.literal_eval(tools.pycompat.to_text(f.read()))
finally:
f.close()
for demo_data in info.get('demo', []):
_logger.info('Loading %s', (demo_data))
tools.convert_file(cr, module_name, demo_data, {}, 'init', True, 'demo', None)
env.cr.commit()
finally:
# Restaurar constraints
AccountJournal.check_use_document = orig_check1
AccountJournal._check_afip_configurations = orig_check2
# ATENCIÓN: La desactivación temporal de constraints a nivel de clase es riesgosa en entornos multi-hilo/multi-worker.
# Para mitigar riesgos de concurrencia, se encapsula la operación en un savepoint y se toma un lock transaccional.
with env.cr.savepoint():
# Lock transaccional para evitar condiciones de carrera (usar un número único para el módulo)
env.cr.execute("SELECT pg_advisory_xact_lock(190001)")
AccountJournal = env.registry['account.journal']
orig_check1 = AccountJournal.check_use_document
orig_check2 = AccountJournal._check_afip_configurations
AccountJournal.check_use_document = lambda self: None
AccountJournal._check_afip_configurations = lambda self: None
try:
for module_name in ['l10n_ar', 'l10n_ar_edi', 'l10n_ar_website_sale']:
_logger.info('Loading demo data from %s' % module_name)
manifest_file = module.module_manifest(module.get_module_path(module_name))
f = tools.file_open(manifest_file, mode='rb')
try:
info = ast.literal_eval(tools.pycompat.to_text(f.read()))
finally:
f.close()
for demo_data in info.get('demo', []):
_logger.info('Loading %s', (demo_data))
tools.convert_file(cr, module_name, demo_data, {}, 'init', True, 'demo', None)
env.cr.commit()
finally:
# Restaurar constraints
AccountJournal.check_use_document = orig_check1
AccountJournal._check_afip_configurations = orig_check2

Copilot uses AI. Check for mistakes.
1 change: 1 addition & 0 deletions l10n_ar_demo/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
'data': [
],
'demo': [
'demo/account_journal_demo.xml',
Comment on lines 41 to +42
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se ha agregado un nuevo archivo de datos demo (demo/account_journal_demo.xml) que crea registros en el modelo account.journal, pero no se incrementó la versión del módulo en la línea 22. Según las convenciones de Odoo, cuando se añaden datos demo que crean nuevos registros, se debe incrementar al menos la versión patch (por ejemplo, de 16.0.1.0.0 a 16.0.1.0.1).

Copilot generated this review using guidance from repository custom instructions.
'demo/account_tax_demo.xml',
'demo/customer_payment_demo.xml',
'demo/supplier_payment_demo.xml',
Expand Down
29 changes: 29 additions & 0 deletions l10n_ar_demo/demo/account_journal_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Crear diarios de retenciones para las empresas demo -->
<!-- Estos normalmente se crean por account_chart_template._create_bank_journals -->
<!-- pero solo si l10n_ar_account_withholding está instalado cuando se aplica el chart template -->
Comment on lines +4 to +6
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

El comentario menciona account_chart_template._create_bank_journals, pero los diarios que se crean tienen type='cash' (líneas 10, 17, 24), no type='bank'. Esto podría generar confusión. Si realmente deberían ser diarios de banco, corrija el tipo; si son correctamente de efectivo, actualice el comentario para reflejar con precisión qué función o proceso debería crearlos.

Suggested change
<!-- Crear diarios de retenciones para las empresas demo -->
<!-- Estos normalmente se crean por account_chart_template._create_bank_journals -->
<!-- pero solo si l10n_ar_account_withholding está instalado cuando se aplica el chart template -->
<!-- Crear diarios de retenciones (tipo 'cash') para las empresas demo -->
<!-- Estos diarios normalmente se crean automáticamente solo si l10n_ar_account_withholding está instalado al aplicar el chart template -->
<!-- Aquí se crean manualmente como 'cash' para asegurar su existencia en los datos demo -->

Copilot uses AI. Check for mistakes.

<record id="withholding_journal_ri" model="account.journal">
<field name="name">Retenciones</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_ri"/>
<field name="code">RET</field>
</record>

<record id="withholding_journal_exento" model="account.journal">
<field name="name">Retenciones</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_exento"/>
<field name="code">RET</field>
</record>

<record id="withholding_journal_mono" model="account.journal">
<field name="name">Retenciones</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_mono"/>
<field name="code">RET</field>
Comment on lines +9 to +26
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Los tres registros de diarios (líneas 8-13, 15-20, 22-27) son casi idénticos, diferenciándose solo en el id del record y la company_id. Todos tienen el mismo name, type y code. Aunque esto es válido en Odoo (ya que el código de diario es único por compañía), considere si estos diarios necesitan algún tipo de diferenciación adicional en el nombre o código para facilitar su identificación en la interfaz, por ejemplo: "Retenciones RI", "Retenciones Exento", "Retenciones Monotributo".

Suggested change
<field name="name">Retenciones</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_ri"/>
<field name="code">RET</field>
</record>
<record id="withholding_journal_exento" model="account.journal">
<field name="name">Retenciones</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_exento"/>
<field name="code">RET</field>
</record>
<record id="withholding_journal_mono" model="account.journal">
<field name="name">Retenciones</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_mono"/>
<field name="code">RET</field>
<field name="name">Retenciones RI</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_ri"/>
<field name="code">RET</field>
</record>
<record id="withholding_journal_exento" model="account.journal">
<field name="name">Retenciones Exento</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_exento"/>
<field name="code">REX</field>
</record>
<record id="withholding_journal_mono" model="account.journal">
<field name="name">Retenciones Monotributo</field>
<field name="type">cash</field>
<field name="company_id" ref="l10n_ar.company_mono"/>
<field name="code">REM</field>

Copilot uses AI. Check for mistakes.
</record>
</data>
</odoo>