26. Creando un módulo con un modelo tipo singleton. Boton con ejecución. Heredar de res.config.settings

 1. Preliminares

Creamos la carpeta por ejemplo my-addons donde guardaremos las aplicaciones que creemos . Comprobamos que el addons_path del fichero de configuración ( en nuestro caso odoo17.conf) apunte a nuestra carpeta.

[options]
addons_path = /home/eduard/MyPython/04.odoo17/my-addons,/home/ximo/MyPython/04.odoo17/odoo/odoo/addons
admin_passwd = ......

Nos situamos en la donde está odoo (~MyPpython/04.odoo17)  y creamos el scaffold de nuestro módulo en la carpeta my-addons/

odoo scaffold xm_grpcastilla my-addons/

Ahora ya tenemos el esqueleto.

Tenemos en principio 2 maneras para hacerlo:

  1. Creando un modelo singleton con un solo registro
  2. Ampliando el modelo "res.config.settings"

2.1 Opción 1: Creando un modelo singleton


Este modelo, al igual que otros modelos tiene sus campos y métodos que en este caso cabe recalcar la ejecución de un script.

Las particularidades que tiene este modelo son:
  1. Método "create" que lanza una excepción si el número de registros es mayor de 1
  2. Método "init" que comprueba la existencia de registros y si no encuentra ninguno crea uno.
  3. Campo "_sql_constraints" que tiene "UNIQUE(id)" que verifica que sea un singleton
Veamos el código del modelo:

from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
import subprocess


class XMGrpCastillaSettings(models.Model):
	_name = 'xm.grpcastilla_settings'
	_description = 'Configuración de la integración con Grupo Castilla de nóminas'

	# Campos del modelo
	borrar_datos = fields.Boolean(
		string='Borrar Datos', 
		help='Borra los datos de la base de datos pertenecientes a capturas anteriores',
		default=False
	)
	ruta_config = fields.Char(
		string='Ruta carpeta configuración', 
		help='Ruta absoluta de la carpeta donde se encuentra la configuración',
		default='home/eduard/kk'
	)
	script_captura = fields.Char(
		string='Ruta script captura',
		help='Ruta absoluta al fichero bsh que ejecuta la captura',
		default='/home/informatica/MyPython/02.llibreries/ximo-python-library/castilla2odoo.sh'
	)


	# Ensure only one record exists by overriding the create method
	@api.model
	def create(self, vals):
		# Check if there is already a record in the model
		if self.search_count([]) >= 1:
			raise ValidationError("You cannot create more than one record in this model.")
		return super(XMGrpCastillaSettings, self).create(vals)

		
	# Automatically create the single record on module installation or server restart
	@api.model
	def init(self):
		if not self.search([]):  # Check if the model has no records
			self.create({
				'borrar_datos': False,
				'ruta_config': '/home/eduard/MyPython/02.llibreries/ximo-python-library/conf',
				'script_captura':  'home/eduard/kk/odoo.yml',
			})

	# Optionally, add a SQL constraint to enforce that only one record exists in the database
	_sql_constraints = [
		('unique_xm_castilla_settings_SINGLETON', 'UNIQUE(id)', 'You can only have one record in this model!')
	]

	def execute_my_script(self):
		# Path to the bash script you want to execute
		#script_path = "/home/eduard/kk/kk.sh"
		script_path = self.script_captura
		param1 = str(self.borrar_datos)
		param2 = self.ruta_config


		try:
			# Execute the bash script using subprocess
			result = subprocess.run([script_path, param1, param2], capture_output=True, text=True, check=True)

			# Return success notification with output from the script
			return {
				'type': 'ir.actions.client',
				'tag': 'display_notification',
				'params': {
					'title': 'Script Executed',
					'message': f'Success: {result.stdout}',
					'type': 'success',
				}
			}
		except subprocess.CalledProcessError as e:
			# Return error notification with output from the script
			return {
				'type': 'ir.actions.client',
				'tag': 'display_notification',
				'params': {
					'title': 'Script Failed',
					'message': f'Error: {e.stderr}',
					'type': 'danger',
				}
			}


Veamos la vista, que para simplificar se ha metido en el mismo fichero el formulario, la acción que abre el formulario y los menús:

Respecto a la acción que abre el formulario:
  1. Primeramente se define un formulario (no interesa tener vista tipo list o tree pues solamente tenemos un único registro)
  2. En el context damos {'form_view_initial_mode':'edit'} para indicar que modifique el registro en el formulario, pues por defecto activa el modo "new" para hacer una alta.
  3. Le damos a la opción 'res-id' el valor "1" para que actue sobre el registro con id=1
En el formulario hemos dado los campos normales y también el "id" para hacer comprobaciones

Respecto a los menús:
  1. Creamos un menu que cuelgue del menú principal de configruación (base.menu_administration) y otro que cuelgue de este y ejecute la acción de abrir el formulario

<odoo>
  <data>
	<!-- 
	********************************************************************************
	01. FORMULARIOS
	01.01. FORMULARIO xm_grpcastilla_settings 
	******************************************************************************** 
	-->
	<record id="view_xm_grpcastilla_settings_form" model="ir.ui.view">
		<field name="name">xm_grpcastilla_settings.form</field>
		<field name="model">xm_grpcastilla_settings</field>
		<field name="arch" type="xml">
			<form string="Configuración de la Aplicacion Grupo Castilla" create="false"  delete="false" edit="true">
				<!-- Button Placement -->
				<header>
					<!-- Add your button inside the header tag to place it at the top -->
					<button name="execute_my_script" type="object" string="Capturar desde Grupo Castilla" class="btn-primary"/>
				</header>
				<group>
				<!-- Fields -->
					<field name="id"/>
					<field name="borrar_datos"/>
					<field name="ruta_config"/>
					<field name="script_captura"/>						
				</group>
				
			</form>
		</field>
	</record>

	<!--
	********************************************************************************
	02. ACCIONES
	02.01.  Acción para el ítem de menú que abre el formulario de configuración de Castilla 
	        Es un model Singleton que sols admet un únic registre
	********************************************************************************
	-->
	<record id="action_xm_grpcastilla_settings" model="ir.actions.act_window">
		<field name="name">Configuración de Grupo Castilla nóminas</field>
		<field name="res_model">xm_grpcastilla_settings</field>
		<!--field name="view_mode">tree,form</field -->
		<field name="view_mode">form</field>
		
		<!--  Inici Singleton	-->
		<field name="view_id" ref="view_xm_grpcastilla_settings_form"/>
		<field name="target">current</field>
		<field name="context">{'form_view_initial_mode':'edit'}</field>
		<field name='form_view_initial_mode':'edit'</field>	<!-- Sols sfecta al registre amb id=1 -->
<!-- Fin singleton--> </record> <!-- ******************************************************************************** 03. MENÚS 03.01. Menu general ******************************************************************************** --> <!-- Castilla Settings App Menu --> <menuitem id="menu_xm_grpcastilla" name="Grupo Castilla" parent="base.menu_administration" sequence="10" /> <!-- Submenú --> <menuitem id="menu_castilla_settings_submenu" name="Configuración" parent="menu_grpcastilla_settings" action="action_xm_grpcastilla_settings" sequence="10" /> </data> </odoo>


2.2 Opción 2: Heredando de res.config.settings

Este modelo







Comentarios

Entradas populares de este blog

4. Desarrollando con Odoo (2). Introducción a modulos, vistas, modelos .. Añadir dependencias externas de Python a Odoo

26. Desarrollando con Odoo (21). IMPORTANTE: Entorno de desarrollo. Instalar odoo. Modulos. scaffold. Recapitulaciones del capítulo 8 (Development, Test and Debug).

8. Desarrollando con Odoo (6). Herencia de clase en modelos. Herencia de vistas. Operaciones numeradas en Odoo ??