Skip to content

2.4. Desenvolupar l'IMS

Fher edited this page Dec 1, 2024 · 16 revisions

Descàrrega i configuració

A continuació s'ofereix un compendi de tota la informació que ofereix aquesta wiki, estructurada i guiada per a facilitar la preparació d'un entorn de desenvolupament per a l'IMS:

  1. Plataforma de desenvolupament: Cal configurar una plataforma de desenvolupament per a poder instal·lar Odoo.

  2. Preparació de l'entorn: Cal seguir la guia de preparació de l'entorn per a deixar el sistema preparat i poder treballar amb Odoo.

  3. Accés remot: Després cal configurar l'accés remot a la màquina per a poder treballar amb comoditat.

  4. Directori de proves: Tot seguit, és necessari configurar un directori de proves on es desenvoluparà el mòdul.

  5. Permisos: El següent pas consisteix en donar els permisos necessaris perquè Odoo pugui accedir al mòdul.

  6. Prerequisits: Cal instal·lar alguns paquets per a que l'IMS funcioni correctament, cal executar les següents comandes: 6.1. apt install git pip -y
    6.2. pip3 install phonenumbers

  7. Instal·lació del mòdul: Finalment, només cal situar-se dins el directori myModules i fer:
    7.1. Clonar el repositori: git clone https://github.com/ElPuig/IMS.git ims
    7.2. Accedir a la carpeta: cd ims
    7.3. Escollir la base de dades (opcional): modificar el paràmetre -i de l'script install.sh per a escollir la base de dades.
    7.4. Instal·lar el mòdul: ./install.sh

  8. Accedir a Odoo: Ja es pot accedir a Odoo fent servir un navegador web, la IP o el hostname i el port 8069 (http://ims-devel:8069). Les credencials predeterminades són:
    Usuari: admin
    Password: admin

Instal·lar les dades de demo:

Es pot instal·lar o actualitzar l'IMS afegint dades de demostració per a fer proves, amb la comanda:
./demo.sh

Reinstal·lar l'IMS durant el desenvolupament:

Es pot actualitzar l'IMS mentre es fan canvis al codi font, per a veure'ls reflectits en la instal·lació i fer-ne proves, amb la comanda:
./update.sh

Icones que fa servir Odoo

Només cal fer servir el cercador i copiar l'exemple. Odoo fa servir els que acaben en "-o" quan n'hi ha alguna variant (per exemple: "fa fa-trash-o").
https://fontawesome.com/v4/icons/

Exemple: el següent bloc de codi permet afegir un botó per esborrar un ítem

<a title="Delete" type="delete" href="#" class="we-button.o_delete_btn" role="button">
   <i class="fa fa-trash-o" aria-hidden="true" />
</a>

Canviar el nom d'un menú existent (nadiu d'Odoo)

Cal cercar el menú dins de "Settings / Techincal / User Interface / Menu Items", es recomana cercar pel nom del menú. Per exemple: "Employees":
image

Una forma de saber si és el menú correcte, és revisar els seus submenús:
image

Un cop trobat el menú, cal accedir al seu ID consultant les metadades:
image

Es mostrarà l'ID:
image

Editant el camp "name" amb XML i aportant el ID correcte, es pot modificar el nom:

<record model="ir.ui.menu" id="hr.menu_hr_employee_user">
   <field name="name">All</field>
</record>

Amagar un menú existent (nadiu d'Odoo)

Afegir el següent codi dins un XML de vista per a sobreescriure'l:

<record model="ir.ui.menu" id="hr.menu_view_employee_category_form">
    <field name="active">false</field>
</record> 

Consultar els detalls sobre com trobar els IDs a l'apartat "Canviar el nom d'un menú existent (nadiu d'Odoo)".

Pintar les cel·les dels llistats

https://www.cybrosys.com/blog/add-colors-to-tree-view-odoo-13

Mostrar alertes als usuaris

Pot resultar útil per a debugar amb Python o simplement per a mostrar alertes als usuaris. https://www.cybrosys.com/blog/raising-exceptions-in-the-odoo-15

Endreçar un desplegable dins un formulari

Si el desplegable depèn d'un camp Many2one, cal indicar l'ordre dins del propi model:

class ims_attendance_schedule(models.Model):
	_name = "ims.attendance_schedule"
	_description = "Attendance schedule: concretes the weekdays data."
	_order = 'attendance_template_id asc, weekday asc, start_time asc'

Editar les vistes predeterminades

A continuació es detallen els passos per a editar una vista existent, sense alterar el codi font original:

  1. Primer cal heretar la vista que es vol modificar:
<record model="ir.ui.view" id="view_contact_form">
   <field name="name">ims.contact.form</field>
   <field name="model">res.partner</field>            
   <field name="inherit_id" ref="base.view_partner_form"/> 
   <field name="arch" type="xml"> 
  1. A continuació, es pot escollir un element fent servir XPath o directament pel nom d'un atribut del model: 2.1. Exemple a partir del nom d'un atribut del model:
<field name="vat" position="after">                    
   <field name="contact_type"/>
   <field name="company_type" attrs="{'invisible': [('contact_type', '!=', 'provider')]}"/>
</field>

2.2. Exemple a partir d'una consulta XPath:

<xpath expr="//page[@name='sales_purchases']" position="attributes">                     
   <attribute name="attrs">{'invisible': [('contact_type', '!=', 'provider')]}</attribute>
</xpath>

2.3. Els detalls sobre els diferents valors de "position" o d'altres elements de modificació, es poden consultar a la documentació oficial: https://www.odoo.com/documentation/16.0/es/developer/reference/backend/views.html#inheritance-specs

Models orientats a les vistes (com simular vistes SQL)

Per a simular vistes cal crear un nou model de dades, que no estarà orientat a la lògica de negoci sinó a proveir d'una estructura per a recollir la informació que ha de mostrar una vista, normalment un llistat o "treeview". El primer que cal decidir és si el model de dades ha de ser persistent (llistat d'elements, com per exemple el de "subject") o si pot ser temporal o "transient" (com el llistat d'alumnes matriculat a assignatures concretes dins un grup, que es mostra dins el formulari de "group"):

  1. Model: funciona com un model de dades normal, amb persistència dins la base de dades, però cal determinar-ne el moment de creació d'aquest model en funció del model de dades original. Com a exemple es pot trobar el model "subject" ja que es permet assignar una assignatura a més d'un nivell d'estudis, però el llistat d'assignatures (que mostra les assignatures agrupades per nivell d'estudis) necessita d'un llistat amb relació 1-1 i no pas 1-N. És per aquest motiu que, quan es crea un nou "subject" o se'n modifiquen els seus estudis, es crea un nou model de vista. Per a fer-ho, s'ha fet de la següent manera:
    1.1. Es crea el model de vista (models.Model) dins el mateix fitxer que el model de dades original (ims_subject_view i ims_subject es troben dins el fitxer subject.py.
    1.2. Es crea un nou atribut cap a la vista, de tipus One2many, amb un mètode compute i store=True. Per exemple: subject_view_ids = fields.One2many(comodel_name="ims.subject_view", inverse_name="subject_id", compute="_compute_subject_views", store=True).
    1.3. Es crea el mètode compute tenint en compte que necessita un @api.depends que indicarà que, quan es modifiquin altres atributs, caldrà tornar a recalcular aquest mètode. Per exemple:
@api.depends("study_ids")
   def _compute_subject_views(self):	        
      for rec in self:
         self.env['ims.subject_view'].search([('subject_id', '=', rec.id)]).unlink()
         for study in rec.study_ids:                
            rec.subject_view_ids.create({
            "level": rec.level,
            "code": rec.code,
            "acronym": rec.acronym,
            "name": rec.name,
            "study_id": study.id,
            "subject_id": rec.id,
         })	 
  1. TransientModel: funciona com un model de dades normal, amb persistència temporal dins la base de dades (s'esborra de tant en tant), però cal determinar-ne el moment de creació d'aquest model en funció del model de dades original. Com a exemple es pot trobar el model "group" perquè es volen mostrar quines matèries cursen els alumnes dins aquest grup (ignorant la resta de matèries que un alumne pugui cursar a altres grups), però el treeview no permet filtrar els resultats d'un camp que és una relació cap a N (existeix l'opció, amb l'atribut domain, però l'ignora). És per aquest motiu que, quan s'obre el formulari d'un "group", es crea un nou model de vista. Per a fer-ho, s'ha fet de la següent manera:
    2.1. Es crea el model de vista (models.TransientModel) dins el mateix fitxer que el model de dades original (ims_enrollment_view i ims_group es troben dins el fitxer group.py.
    2.2. Es crea un nou atribut cap a la vista, de tipus One2many, amb un mètode compute. Per exemple: enrollment_view_ids = fields.One2many(string="Enrollment", comodel_name="ims.enrollment_view", inverse_name="group_id", compute="_compute_enrollment_ids").
    2.3. Es crea el mètode compute sense cap @api.depends, de tal manera que s'activarà només en obrir el formulari. Per exemple:
def _compute_enrollment_ids(self):							
   for rec in self:				
      self.env['ims.enrollment_view'].search([('group_id', '=', rec.id)]).unlink()			
      for student in self.env['ims.enrollment'].read_group(domain=[('group_id', '=', rec.id)], fields=['student_id'], groupby=['student_id']):	
         sid = student['student_id'][0]	
         subs = self.env["ims.enrollment"].search([("group_id", "=", rec.id), ('student_id', '=', sid)]).mapped("subject_id")		
         rec.enrollment_view_ids.create({
            "group_id": rec.id,
            "student_id": sid,
            "subject_ids": subs,					
         })		

Mes informació sobre com obtenir dades agrupades o com crear-ne nous registres de forma manual:

Obrir un model de dades diferent en fer click sobre un element

TODO:

CSS personalitzat

TODO:

JavaScript personalitzat

TODO: