11. Zolteka para desarrolladores: widgets, calendario, avisos y tablero

⚠️ Esta página es solo para desarrolladores. No hace falta para usar Zolteka. Explica cómo otro plugin puede aprovechar lo que ya trae Zolteka sin copiarlo.

Requisitos: Zolteka 2.0 o superior, FacturaScripts 2026.65 o superior y PHP 8.1 o superior.

📍 En esta página:

Antes de empezar

  • Comprueba siempre que Zolteka está. Antes de usar una clase o un método de Zolteka, compruébalo con class_exists() (y method_exists() si llamas a un método concreto). Si Zolteka no está activo, tu plugin debe seguir funcionando.
  • Registra en Init::init(), sin consultas a la base de datos. Si tu plugin se desactiva, sus registros desaparecen solos.
  • No hay garantía de compatibilidad entre versiones. Lo marcado como experimental puede cambiar en la siguiente versión.
  • Las acciones AJAX de Zolteka no son una API HTTP pública. Úsalas solo desde pantallas del propio ERP, con la sesión iniciada y el token CSRF (multireqtoken).
use FacturaScripts\Plugins\Zolteka\Lib\Kanban\KanbanRegistry;

public function init(): void
{
    if (class_exists(KanbanRegistry::class)) {
        KanbanRegistry::register(new MiTableroProvider());
    }
}

1. Widgets para tus vistas XML

Widgets de Zolteka para vistas XML: zPctBadge, zImageProd, zHtml y zLineasProducto

Las propiedades comunes a todos los widgets (fieldname, required, readonly, onclick, opciones de color) funcionan igual que en el núcleo: consulta la página general de widgets de FacturaScripts. Aquí solo van las propiedades propias de cada widget.

zPctBadge

Muestra un porcentaje como etiqueta de color. Es el que ves en los listados de facturas de cliente y de proveedor. A diferencia del widget nativo percentage, pinta el valor con un color según umbrales y solo se usa en listados.

<column name="pct-cobrado" display="right" order="500">
    <widget type="zPctBadge" fieldname="pct_cobrado"/>
</column>

Propiedades

  • fieldname: campo con el porcentaje. Obligatorio. Si está vacío se muestra un guion (-).
  • decimal: decimales, de 0 a 6. Por defecto, 1.
  • tonefield: campo del modelo con el color ya calculado. Por defecto, {fieldname}_tone. Si trae valor, manda sobre los umbrales.
  • tonesuccess, tonewarning, tonedanger, toneinfo, toneprimary, tonesecondary: umbral a partir del cual se usa ese color. Gana el umbral más alto alcanzado. Opcionales.
  • titlekey: clave de traducción del texto de ayuda al pasar el ratón. Opcional.

Colores admitidos: success, warning, danger, info, primary y secondary. Si no hay color ni se alcanza ningún umbral, sale warning.

Ejemplo con umbrales: rojo por debajo del 50 %, amarillo desde el 50 % y verde al llegar al 100 %, sin decimales.

<column name="pct-cobrado" display="right" order="500">
    <widget type="zPctBadge" fieldname="pct_cobrado" decimal="0"
            tonedanger="0" tonewarning="50" tonesuccess="100" readonly="true"/>
</column>

Visualización en listados

Widget zPctBadge en el listado de facturas de cliente: columnas Cobrado y Por cobrar con badges de porcentaje en rojo y verde

Notas: el modelo debe tener la propiedad indicada en fieldname, ya sea una columna o un valor calculado.

zImageProd

Muestra en un listado la miniatura de la primera imagen del producto, incluidas las de sus variantes si quieres.

<!-- Extension/XMLView/ListProducto.xml de tu plugin -->
<view>
    <columns>
        <column name="image" order="90">
            <widget type="zImageProd" fieldname="referencia"/>
        </column>
    </columns>
</view>

Propiedades

  • fieldname: campo del producto, normalmente referencia. Obligatorio.
  • thumbwidth: ancho de la miniatura en píxeles. Por defecto, 75.
  • thumbheight: alto de la miniatura en píxeles. Por defecto, 75.
  • variants: true incluye las imágenes de las variantes y false las excluye. Por defecto, true.

Ejemplo con opciones: miniatura más pequeña y solo imágenes del producto principal.

<widget type="zImageProd" fieldname="referencia" thumbwidth="50" thumbheight="50" variants="false"/>

Visualización en listados

Todavía no hay captura: ningún plugin publicado usa aún este widget.

Notas

  • El modelo debe tener el método getImages(), como Producto. Si no lo tiene, la celda sale vacía.
  • Zolteka no añade esta columna al listado de productos por su cuenta: la añade tu plugin con una extensión de la vista, como en el ejemplo.

zHtml

Muestra en una celda de listado un texto con negritas, cursivas y saltos de línea. No tiene propiedades propias.

<column name="resumen" order="200">
    <widget type="zHtml" fieldname="resumen"/>
</column>

Visualización en listados

Todavía no hay captura: ningún plugin publicado usa aún este widget.

Notas

  • Solo admite las etiquetas strong, em, b, i y br, sin atributos. Cualquier otra se muestra como texto.
  • Si el campo está vacío se muestra un guion (-).
  • No es un editor ni sirve para HTML libre. Se llama zHtml para no chocar con widgets html de otros plugins.

zLineasProducto

Editor de líneas de producto dentro de una ficha: referencia, descripción, cantidad, precio, si es facturable y, si quieres, una segunda línea de detalle. Las líneas se guardan con el mismo botón «Guardar» de la ficha.

<!-- XMLView/EditMiParte.xml -->
<group name="lineas" numcolumns="12">
    <column name="mi-plugin-lineas" numcolumns="12" order="100">
        <widget type="zLineasProducto"/>
    </column>
</group>

Propiedades

  • autoadd: true añade una fila vacía nueva al elegir un producto; con false aparece el botón «Añadir línea». Por defecto, false.
  • prices: false oculta la columna de precio. Por defecto, true.
  • billable: false oculta la casilla «Facturable». Por defecto, true.
  • maxlines: número máximo de líneas, bloqueadas incluidas. Por defecto, 0 (sin límite). Usa el mismo valor al guardar.
  • emptyquantity: true deja vacía la cantidad de las filas nuevas en vez de poner 1. Por defecto, false.
  • quantityfield: propiedad de la línea de la que se lee la cantidad. Por defecto, cantidad.
  • quantitytitle: clave de traducción del rótulo de la cantidad. Por defecto, quantity.
  • pricetitle: clave de traducción del rótulo de la columna de precio. Por defecto, zolteka-precio-unitario («Precio unitario»).
  • lines: tipo de línea, para fichas con más de un tipo. Opcional.
  • detail: plantilla Twig, sin extensión, de la segunda línea de cada fila. Opcional.
  • autocompleteaction: acción que responde a la búsqueda de productos. Por defecto, autocomplete-producto-lineas.
  • autocompletefilter: filtro que se envía con la búsqueda de productos. Opcional.

Las propiedades true/false también admiten 1/0, yes/no y on/off. El título del bloque sale del title de la columna; si no hay, se muestra «Productos y servicios».

Ejemplo con opciones: máximo de 20 líneas y sin la casilla «Facturable».

<widget type="zLineasProducto" maxlines="20" billable="false"/>

Visualización en fichas

Bloque de líneas en una ficha: cabecera Líneas, Precio unitario, Facturable y Añadir línea

Notas

  • El widget no guarda nada por sí solo. Tu controlador tiene que guardar las líneas con ZLineasProductoSync y responder a la búsqueda de productos (puede usar ZLineasProductoBuscador).
  • El modelo de la ficha necesita el método getLineasProducto(): array. Son opcionales getLineasProductoBloqueadas() y getLineasProductoCodcliente().
  • En un listado la celda sale vacía.
  • Al elegir un producto, el autocomplete pone el precio unitario sin IVA, el mismo que usaría FacturaScripts en un presupuesto de ese cliente con esa referencia. Si no hay cliente o el Core no encuentra el producto, se usa el precio neto de la variante.

Ejemplo de controlador: un EditController cuyo modelo MiParte tiene líneas MiParteLinea con el campo idparte. Guarda las líneas con el mismo «Guardar» de la ficha y responde a la búsqueda de productos.

use FacturaScripts\Plugins\Zolteka\Lib\ZLineasProductoBuscador;
use FacturaScripts\Plugins\Zolteka\Lib\ZLineasProductoSync;
use FacturaScripts\Plugins\MiPlugin\Model\MiParteLinea;

protected function editAction(): bool
{
    if (false === parent::editAction()) {
        return false;
    }

    // guarda las líneas en el mismo «Guardar» de la ficha
    ZLineasProductoSync::syncFromHttp(
        $this->permissions->allowUpdate,
        $this->request,
        MiParteLinea::class,
        'idparte',
        (int) $this->getModel()->id(),
        maxLineas: 20 // el mismo valor que maxlines="20" del XML
    );
    return true;
}

protected function execPreviousAction($action)
{
    // autocompletado de productos del widget (action por defecto)
    if ($action === 'autocomplete-producto-lineas') {
        $this->setTemplate(false);
        ZLineasProductoBuscador::autocompleteJson($this->request, $this->response);
        return false;
    }

    return parent::execPreviousAction($action);
}

En una ficha nueva las líneas se guardan cuando ya existe el registro, por eso el ejemplo usa editAction(). Si tu plugin también debe funcionar sin Zolteka, comprueba antes class_exists(ZLineasProductoSync::class).

2. Conectar tu plugin al calendario

Cada evento de tu plugin se identifica con origen_tipo y origen_id (el id de tu registro). Los eventos creados a mano en la agenda usan general; tu plugin usa su propio nombre corto, por ejemplo miplugin.

  • Crear o actualizar eventos desde tu modelo: en saveAfter(), busca el evento por origen_tipo y origen_id en ZoltekaCalendarEvent, rellénalo y guárdalo. En deleteAfter(), bórralo.
  • Mostrar el calendario en tu pantalla: reutiliza las plantillas _calendar_timegrid o _calendar_base con allow_create y tu origen_tipo, y el modal _calendar_event_modal. No copies su HTML ni su JavaScript.
  • Guardar, mover y borrar: delega en CalendarEventAjax en lugar de repetir esa lógica.
  • Recordatorios por email: implementa CalendarNotificationProviderInterface y regístralo con CalendarNotificationRegistry::register().
  • Grupos de asistentes propios (opcional): CalendarParticipantGroupRegistry::register() con un CalendarParticipantGroupProviderInterface.

3. Avisos en la campana y en el móvil

Registra tu propio tipo de aviso con NotificationTypeRegistry::register() y un NotificationTypeInterface. El tipo decide su texto, icono, permiso, si abre ventana emergente y si se envía al móvil. Para crear avisos usa ZoltekaNotificationManager::emit(), que solo sirve para tipos personales y emisibles; Zolteka no los duplica y solo los entrega a usuarios activos con permiso.

4. Tablero (Kanban)

  • Tablero propio: implementa KanbanProviderInterface y regístralo con KanbanRegistry::register(). Opcionales: KanbanDetalleInterface (ventana de detalle), KanbanFiltrosInterface (barra de filtros) y KanbanOrdenableInterface (ordenar por). Los cuatro tableros de presupuestos y pedidos ya los registra Zolteka.
  • Etiquetas en las tarjetas (experimental, desde la 1.77): KanbanEtiquetaRegistry::register() con un KanbanEtiquetaProviderInterface.
  • Criterios de «Ordenar por» (experimental, desde la 1.77): KanbanOrdenRegistry::register() con un KanbanCriterioOrdenInterface. Tu plugin no escribe SQL: indica la tabla y la columna de donde sale el dato.
  • Los pasos que crean otro documento siguen haciéndose desde la ficha. No copies el controlador, el JavaScript ni el CSS del tablero.

5. Panel de mando

  • Añadir un bloque debajo de los recibos: crea en tu plugin la vista Extension/View/DashBoardZolteka_AfterReceiptsSummary_MiPlugin.html.twig. El sufijo con el nombre de tu plugin evita que otro plugin con el mismo archivo tape el tuyo.
  • Excluir datos de los indicadores de tesorería: DashBoardZolteka::addTreasuryCycleInvoiceExclude() (facturas) y DashBoardZolteka::addTreasuryReceiptPaymentExclude() (formas de pago). Compruébalos antes con class_exists() y method_exists().

Condiciones de uso

Esta página explica cómo puedes usar desde tu propio plugin las clases, extensiones, eventos, widgets e integraciones de Zolteka. Desarrolla el punto 1.c del Contrato de licencia freeware de Zolteka y no lo sustituye. Si hay alguna diferencia, manda el contrato.

1. Lo que puedes hacer

  • Crear plugins complementarios, gratuitos o de pago, que se conecten a Zolteka: llamar a sus clases, extenderlas o heredar de ellas, usar sus extensiones, eventos y widgets, leer sus datos e integrarte con el calendario y el resto de funciones documentadas en esta página. Hacerlo desde tu plugin no modifica el código de Zolteka y está permitido (punto 1.c).
  • Instalar Zolteka y tus plugins complementarios a tus clientes y cobrar por tus servicios, pero no por Zolteka. Descárgalo siempre de los canales oficiales (puntos 1.b y 4).
  • Cambiar el código de Zolteka solo para uso interno en tu propia instalación. Esos cambios no pueden instalarse en instalaciones de terceros, incluidos tus clientes, ni distribuirse. Si encuentras una corrección que afecte a otros, comunícasela al autor (punto 1.d).

2. Lo que no puedes hacer

  • Copiar, reutilizar o adaptar todo o una parte sustancial del código, la estructura o las vistas de Zolteka dentro de tu plugin. Tu plugin se conecta a Zolteka, no lo incluye (punto 2.c).
  • Vender, alquilar, sublicenciar o redistribuir Zolteka, ni publicarlo, ni una copia modificada, con otro nombre o autoría (puntos 2.a, 2.b y 2.c).
  • Eliminar, ocultar, alterar o redirigir desde tu plugin los avisos, los logotipos, los nombres «Zolteka» o «Carlos Moreno Gil» o los enlaces a zolteka.com. La única excepción son las herramientas oficiales del autor que lo permiten expresamente, como zMarcaBlanca, en sus condiciones. Los avisos de autoría y copyright se mantienen siempre (puntos 2.d y 3).

Nada de esto limita lo que la ley permite en todo caso, como la interoperabilidad (art. 100 de la Ley de Propiedad Intelectual).

3. Uso del nombre «Zolteka»

Puedes indicar que tu plugin es «compatible con Zolteka» o que «requiere Zolteka». No puedes usar el nombre ni el logotipo como parte del nombre de tu plugin o de tu marca, ni dar a entender que Zolteka o su autor lo respaldan, lo revisan o lo mantienen.

4. Estabilidad de la API y sin garantía

  • Esta API se ofrece «tal cual», como el resto del plugin (punto 8). Intentamos mantenerla estable, pero puede cambiar entre versiones de Zolteka. Los cambios incompatibles se anunciarán en el CHANGELOG y, cuando sea posible, con una versión de margen antes de retirar algo.
  • Usa solo lo que se documenta en esta página. Cualquier otra clase, método o tabla es interna y puede cambiar sin aviso.
  • No ofrecemos soporte a plugins de terceros. Cada desarrollador responde de su plugin ante sus clientes.
  • El autor no responde de los daños causados por plugins de terceros ni por cambios en la API, salvo dolo o culpa grave y en lo que la ley no permita excluir (punto 8).

5. Ejemplos de código de esta página

Puedes copiar, adaptar y distribuir los ejemplos de código de esta página dentro de tus plugins, gratuitos o de pago, sin pedir permiso ni citar la fuente. Se ofrecen «tal cual», sin garantía. Este permiso solo cubre los ejemplos de esta página: el código de Zolteka sigue sujeto a su contrato de licencia freeware.


Titular: Carlos Moreno Gil, bajo el nombre comercial Zolteka · carlos.moreno@zolteka.com · https://zolteka.com

Cookies
Usamos cookies necesarias para el funcionamiento del sitio y cookies opcionales para recordar tus preferencias y mejorar tu experiencia. Puedes aceptarlas todas, rechazarlas o configurar tus preferencias

Soporte