addons portados en el repo de ecocentral

This commit is contained in:
GitHub Copilot 2026-08-07 16:34:38 +02:00
parent f2194c5367
commit 65818b0155
72 changed files with 2474 additions and 3 deletions

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import models

View file

@ -0,0 +1,22 @@
# Copyright 2026 Ecocentral, Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Partner CCPAE",
"summary": "Añade los datos del registro de operador CCPAE a los contactos.",
"version": "18.0.1.0.0",
"development_status": "Beta",
"author": "Criptomart",
"website": "https://github.com/Ecocentral/ecocentral",
"category": "Localization/Europe",
"license": "AGPL-3",
# `mail` es imprescindible: los dos campos son `tracking=True` y eso
# necesita `mail.thread` sobre `res.partner`. No hay modelos nuevos, así
# que tampoco hay `security/`.
"depends": [
"base",
"mail",
],
"data": [
"views/res_partner_views.xml",
],
}

View file

@ -0,0 +1,49 @@
# Copyright 2026 Ecocentral, Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
"""Renombrar l'xml_id de la vista heretada del formulari de contacte.
A la 17.0 la vista es deia `l10n_es_partner_ccpae.view_partner_form`, un nom
que xoca visualment amb `base.view_partner_form` i que no segueix la convenció
del repo (`<model>_view_form_<mòdul>`). A la 18.0 passa a dir-se
`res_partner_view_form_ccpae`.
Sense aquest script l'actualització continuaria funcionant —Odoo crearia una
vista nova i esborraria l'antiga a `_process_end`— però pel mig hi hauria dues
vistes heretades equivalents injectant la mateixa pàgina al formulari, i es
perdrien les personalitzacions que algú hagués fet sobre el registre existent.
Renombrant a `ir_model_data` es reaprofita la mateixa `ir.ui.view`.
"""
import logging
_logger = logging.getLogger(__name__)
RENAMED_XMLIDS = [
# (model, nom antic, nom nou)
("ir.ui.view", "view_partner_form", "res_partner_view_form_ccpae"),
]
def migrate(cr, version):
if not version:
return
for model, old_name, new_name in RENAMED_XMLIDS:
cr.execute(
"""
UPDATE ir_model_data
SET name = %s
WHERE module = 'l10n_es_partner_ccpae'
AND name = %s
AND model = %s
AND NOT EXISTS (
SELECT 1 FROM ir_model_data
WHERE module = 'l10n_es_partner_ccpae'
AND name = %s
)
""",
(new_name, old_name, model, new_name),
)
if cr.rowcount:
_logger.info(
"l10n_es_partner_ccpae: xml_id %s renombrat a %s", old_name, new_name
)

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import res_partner

View file

@ -0,0 +1,26 @@
# Copyright 2026 Ecocentral, Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields
from odoo import models
# Organismo de control por defecto: el código CCPAE de Ecocentral. Los
# proveedores certificados por otro consejo regulador lo sobreescriben a mano.
DEFAULT_CCPAE_ORGANISMO = "ES-ECO-019-CT"
class ResPartner(models.Model):
_inherit = "res.partner"
ccpae_operador = fields.Char(
string="Nº de Operador",
tracking=True,
help="Número de operador en el registro del consejo regulador de "
"producción agraria ecológica.",
)
ccpae_organismo = fields.Char(
string="Organismo regulador",
default=DEFAULT_CCPAE_ORGANISMO,
tracking=True,
help="Código del organismo de control que certifica al operador.",
)

View file

@ -0,0 +1,13 @@
Añade a los contactos de tipo empresa los datos del registro de operador del
consejo regulador de producción agraria ecológica (CCPAE):
* **Nº de Operador**: el número con el que el proveedor está inscrito en el
registro.
* **Organismo regulador**: el código del organismo de control que lo certifica,
por defecto ``ES-ECO-019-CT`` (CCPAE).
Ambos campos tienen seguimiento en el chatter, de forma que cualquier cambio en
la certificación de un proveedor queda registrado.
A pesar del nombre, el módulo **no** depende de ``l10n_es_partner`` de OCA: solo
necesita ``base`` y ``mail``.

View file

@ -0,0 +1,8 @@
#. Abre un contacto de tipo *Empresa* (los campos están ocultos en los
contactos de tipo persona).
#. Ve a la pestaña **CCPAE**.
#. Rellena el *Nº de Operador*. El *Organismo regulador* viene precargado con
``ES-ECO-019-CT``; cámbialo si el proveedor está certificado por otro
consejo regulador.
Los cambios en ambos campos quedan registrados en el chatter del contacto.

View file

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import test_res_partner_ccpae

View file

@ -0,0 +1,67 @@
# Copyright 2026 Ecocentral, Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import TransactionCase
from odoo.tests.common import tagged
from odoo.addons.l10n_es_partner_ccpae.models.res_partner import DEFAULT_CCPAE_ORGANISMO
@tagged("post_install", "-at_install")
class TestResPartnerCcpae(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partner = cls.env["res.partner"].create(
{
"name": "Productor Ecològic Test",
"is_company": True,
}
)
# `create` crida `_track_discard()`, que apunta `None` com a valors
# inicials del registre per no traçar la pròpia creació. Mentre aquest
# `None` hi sigui, cap `write` posterior deixa rastre. Buidant el
# precommit aquí es descarta i els tests ja poden traçar.
cls._flush_tracking(cls.env)
@staticmethod
def _flush_tracking(env):
env.flush_all()
env.cr.precommit.run()
def _tracked_fields(self):
"""Camps amb rastre al xatter del contacte, després d'un `write`.
`mail.thread.write()` no crea el `mail.message` de seguiment al moment:
el deixa encuat com a callback de precommit (és el que desencalla
`MailCommon.flush_tracking` del core). I un cop creat cal invalidar el
contacte, perquè `message_ids` ja s'havia llegit i el one2many es queda
amb el valor antic a la memòria cau.
"""
self._flush_tracking(self.env)
self.partner.invalidate_recordset()
return self.partner.message_ids.tracking_value_ids.mapped("field_id.name")
def test_organismo_default(self):
"""Un contacte nou porta el codi del CCPAE per defecte."""
self.assertEqual(self.partner.ccpae_organismo, DEFAULT_CCPAE_ORGANISMO)
self.assertFalse(self.partner.ccpae_operador)
def test_campos_con_seguimiento(self):
"""Escriure als camps CCPAE deixa rastre al xatter."""
self.partner.write({"ccpae_operador": "CT-12345"})
self.assertIn(
"ccpae_operador",
self._tracked_fields(),
"El canvi de ccpae_operador ha de quedar registrat al xatter",
)
self.partner.write({"ccpae_organismo": "ES-ECO-020-CT"})
self.assertIn("ccpae_organismo", self._tracked_fields())
def test_vista_heredada_valida(self):
"""La vista heretada s'ancora bé al formulari de `base` de la 18.0."""
view = self.env.ref("l10n_es_partner_ccpae.res_partner_view_form_ccpae")
arch = self.env["res.partner"].get_view(view.id, "form")["arch"]
self.assertIn("ccpae_operador", arch)
self.assertIn("ccpae_organismo", arch)

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
Copyright 2026 Ecocentral, Criptomart
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="res_partner_view_form_ccpae" model="ir.ui.view">
<field name="name">res.partner.form.ccpae</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="arch" type="xml">
<xpath expr="//page[@name='sales_purchases']" position="after">
<page name="ccpae" string="CCPAE" invisible="not is_company">
<group name="ccpae_group">
<field name="ccpae_operador" />
<field name="ccpae_organismo" />
</group>
</page>
</xpath>
</field>
</record>
</odoo>