diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..2006330eb4 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,155 @@ +# AGENTS.md + +Este archivo proporciona contexto y reglas para agentes de IA que trabajan sobre este repositorio. + +## Propósito + +FacturaScripts es un software ERP y CRM de código abierto escrito en PHP. Permite gestionar facturación, contabilidad, +inventario, clientes, proveedores, informes y análisis. La aplicación está diseñada con una arquitectura modular y +extensible mediante plugins. + +--- + +## Stack técnico + +Backend + +- PHP >= 8.0 +- MySQL, MariaDB o PostgreSQL +- Composer + +Frontend + +- Bootstrap 5 +- Twig (plantillas) +- jQuery +- Select2 +- Chart.js + +Herramientas de desarrollo + +- PHPUnit (tests) +- PHPStan (análisis estático) +- PHPCS (estándares de código) + +--- + +## Estructura del proyecto + +Código principal: + +Core/ + +Directorios más importantes: + +- Core/Controller/ → controladores de páginas +- Core/Model/ → modelos de datos (entidades de base de datos) +- Core/Lib/ → lógica de negocio y utilidades +- Core/Table/ → definición XML de tablas de base de datos +- Core/XMLView/ → definición XML de formularios y listados +- Core/View/ → plantillas Twig +- Core/Worker/ → tareas en segundo plano +- Core/Translation/ → traducciones + +Otros directorios: + +- Dinamic/ → clases generadas automáticamente +- Test/ → pruebas automatizadas +- vendor/ → dependencias PHP +- node_modules/ → dependencias JavaScript + +--- + +## Arquitectura general + +Controladores +→ gestionan las peticiones y acciones de las páginas. + +Modelos +→ representan entidades de base de datos. + +Lib +→ contiene la lógica de negocio y servicios reutilizables. + +XMLView +→ define formularios y listados de forma declarativa. + +Tablas XML +→ define la estructura de las tablas de base de datos. + +--- + +## Reglas de arquitectura + +Los agentes deben seguir estas reglas: + +- La lógica de negocio debe ir en Core/Lib. +- Los controladores deben ser ligeros. +- Los modelos representan tablas de base de datos. +- La estructura de la base de datos se define en Core/Table mediante XML. +- Los formularios y listados se definen en Core/XMLView. +- Las plantillas de interfaz usan Twig en Core/View. +- No modificar código dentro de vendor/ o node_modules/. + +--- + +## Código generado + +El directorio Dinamic/ contiene clases generadas automáticamente. Los agentes nunca deben modificar archivos dentro de +Dinamic/. + +--- + +## Sistema de plugins + +FacturaScripts está diseñado para ser extendido mediante plugins. + +Los plugins pueden: + +- añadir controladores +- extender modelos +- modificar vistas XML +- añadir campos a tablas +- modificar comportamiento del sistema + +Siempre que sea posible, se debe preferir crear o modificar un plugin en lugar de modificar el núcleo del sistema. +Además, los plugins deben usar extensiones principalmente, antes que usar herencia. + +--- + +## Flujo de trabajo recomendado + +Cuando se implementa una funcionalidad o se corrige un error: + +1. Identificar el módulo afectado (Controlador, Modelo o Lib). +2. Implementar la lógica en Core/Lib si es lógica de negocio. +3. Modificar o crear modelos si se necesita acceso a base de datos. +4. Modificar XMLView si hay cambios en formularios o listados. +5. Actualizar la estructura de base de datos mediante XML en Core/Table. +6. Añadir o actualizar pruebas en Test/. + +--- + +## Comandos y desarrollo + +Los comandos de desarrollo se documentan en: + +`ia/DEVELOPMENT.md` + +Este archivo contiene cómo instalar dependencias, ejecutar tests, verificar estilo y usar `fsmaker` para generar +plugins. + +--- + +## Skills + +Consultar el siguiente archivo para ver todas las skills disponibles: +`ai/skills.yaml` + +Skills más utilizadas: + +- use-tools → uso de la clase Tools +- use-translator → uso del traductor (Translator) +- api-usage → uso de la API (Endpoints, tokens) +- use-http → uso de la clase Http (Peticiones externas) +- extensions-and-hooks → uso de pipes (PHP) y ganchos (Twig) para extensiones \ No newline at end of file diff --git a/ai/DEVELOPMENT.md b/ai/DEVELOPMENT.md new file mode 100644 index 0000000000..f92c57244f --- /dev/null +++ b/ai/DEVELOPMENT.md @@ -0,0 +1,67 @@ +# Guía de desarrollo - FacturaScripts + +Este archivo contiene los comandos más importantes para el desarrollo y mantenimiento del proyecto. + +--- + +## Instalación de dependencias + +- Instalar las dependencias de PHP con Composer: + + ``` + composer install + ``` + +- Instalar las dependencias de JavaScript con npm: + + ``` + npm install + ``` + +## Ejecutar tests + +Para ejecutar las pruebas unitarias del proyecto, utiliza: + +``` +vendor/bin/phpunit +``` + +## Análisis estático + +Para realizar un análisis estático del código en el directorio `Core` con PHPStan: + +``` +vendor/bin/phpstan analyse Core +``` + +## Verificar y corregir estilo de código + +- Verificar el estilo de código con PHP_CodeSniffer: + + ``` + vendor/bin/phpcs + ``` + +- Corregir automáticamente los errores de estilo: + + ``` + vendor/bin/phpcbf + ``` + +--- + +## Instalación de fsmaker + +`fsmaker` es una herramienta CLI diseñada para acelerar el desarrollo de plugins para FacturaScripts. + +Para instalar `fsmaker` globalmente con Composer, ejecuta: + +``` +composer global require facturascripts/fsmaker +``` + +Luego, asegúrate de que el binario esté en tu PATH creando un enlace simbólico: + +``` +sudo ln -s ~/.config/composer/vendor/bin/fsmaker /usr/local/bin/fsmaker +``` \ No newline at end of file diff --git a/ai/README.md b/ai/README.md new file mode 100644 index 0000000000..0e204fd89b --- /dev/null +++ b/ai/README.md @@ -0,0 +1,25 @@ +# AI Docs + +Esta carpeta contiene documentación breve y operativa para asistentes de IA. + +## Estructura +- `../AGENTS.md`: contexto general del proyecto +- `./skills.yaml`: índice de skills disponibles +- `./DEVELOPMENT.md`: guía para desarrolladores +- `./skills/*.md`: instrucciones específicas por tipo de tarea + +## Regla práctica +- Lo global y estable va en `AGENTS.md` +- Lo específico de una tarea va en una skill +- No duplicar reglas en demasiados archivos + +## Cómo añadir una nueva skill +1. Crear un archivo en `skills/` +2. Añadir su entrada en `skills.yaml` +3. Mantenerla corta, concreta y accionable + +## Cuándo crear una skill nueva +Crear una skill nueva si: +- una tarea se repite a menudo, +- requiere pasos específicos, +- los agentes suelen equivocarse en ese tipo de cambio. \ No newline at end of file diff --git a/ai/skills.yaml b/ai/skills.yaml new file mode 100644 index 0000000000..e2012e4d46 --- /dev/null +++ b/ai/skills.yaml @@ -0,0 +1,77 @@ +version: 1 + +skills: + - id: use-tools + title: Uso de la clase Tools + file: ai/skills/use-tools.md + when_to_use: + - formatear fechas, números o dinero + - operaciones con archivos y carpetas + - obtener configuraciones o ajustes + tags: [tools, utilities, format] + + - id: use-translator + title: Uso del traductor (Translator) + file: ai/skills/use-translator.md + when_to_use: + - traducir textos o cadenas + - gestionar idiomas y traducciones + tags: [translation, i18n] + + - id: model-management + title: Gestión de Modelos (ModelClass) + file: ai/skills/model-management.md + when_to_use: + - operaciones CRUD (Crear, Leer, Actualizar, Borrar) + - buscar registros en la base de datos + - persistencia de datos + tags: [model, crud, database] + + - id: table-definition + title: Definición de Tablas (XML) + file: ai/skills/table-definition.md + when_to_use: + - crear o modificar tablas de base de datos + - definir columnas y restricciones + tags: [table, xml, database, schema] + + - id: xml-view-definition + title: Definición de Vistas (XMLView) + file: ai/skills/xml-view-definition.md + when_to_use: + - crear o modificar listados y formularios + - definir widgets y visualización + tags: [view, xml, ui, forms, list] + + - id: plugin-development + title: Extensión mediante Plugins + file: ai/skills/plugin-development.md + when_to_use: + - crear nuevos plugins + - extender modelos o controladores del núcleo + - modularidad y extensibilidad + tags: [plugin, extension, modularity] + + - id: api-usage + title: Uso de la API + file: ai/skills/api-usage.md + when_to_use: + - interactuar con FacturaScripts desde aplicaciones externas + - crear nuevos endpoints de API + tags: [api, rest, json, authentication] + + - id: use-http + title: Uso de la clase Http + file: ai/skills/use-http.md + when_to_use: + - realizar peticiones HTTP externas desde FacturaScripts + - consumir servicios web de terceros + tags: [http, curl, request, client] + - id: extensions-and-hooks + title: Extensiones y Ganchos (Pipes/Hooks) + file: ai/skills/extensions-and-hooks.md + when_to_use: + - extender funcionalidad sin usar herencia + - añadir contenido dinámico en plantillas Twig + - interceptar acciones del núcleo + tags: [extension, pipe, hook, twig, plugin] \ No newline at end of file diff --git a/ai/skills/api-usage.md b/ai/skills/api-usage.md new file mode 100644 index 0000000000..08cd701a85 --- /dev/null +++ b/ai/skills/api-usage.md @@ -0,0 +1,107 @@ +# Uso de la API en FacturaScripts + +FacturaScripts proporciona una API RESTful para interactuar con el sistema de forma programática. La API permite tanto el acceso a modelos existentes como la creación de endpoints personalizados. + +## Estructura de la URL + +La URL base para la API es: `/api/{version}/{resource}` + +- **Versión**: Actualmente es `3`. +- **Recurso**: El nombre del recurso (ej: `productos`, `facturas`, `clientes`). + +## Autenticación + +La API requiere un token de autenticación que debe enviarse en las cabeceras HTTP: + +- `Token`: Tu clave de API generada en el panel de control. + +## Modelos automáticos (APIModel) + +Por defecto, FacturaScripts expone todos los modelos situados en `Dinamic/Model` a través de la API de forma automática mediante la clase `APIModel`. Los nombres de los recursos se pluralizan (ej: `producto` -> `productos`). + +Soportan las siguientes operaciones estándar: +- `GET /api/3/{recurso}`: Listar registros (soporta filtros, limit, offset y sort). +- `GET /api/3/{recurso}/{id}`: Obtener un registro específico. +- `POST /api/3/{recurso}`: Crear un nuevo registro. +- `PUT /api/3/{recurso}/{id}`: Actualizar un registro. +- `DELETE /api/3/{recurso}/{id}`: Eliminar un registro. + +## Añadir un endpoint personalizado + +Existen dos formas de ampliar la API: + +### 1. Añadir un Recurso +Todos los modelos listados en `Dinamic/Model` apareceran como recursos disponibles. + + +### 2. Añadir un Endpoint de Acción (ApiController) +Para endpoints que ejecutan acciones específicas (ej: `crearFactura`): + +1. Crea un controlador en `Plugins/{TuPlugin}/Controller/ApiController{Accion}.php`. +2. La clase debe heredar de `FacturaScripts\Core\Template\ApiController`. +3. Implementa el método `runResource()`. +4. **IMPORTANTE**: Debes registrar el endpoint en el archivo `Init.php` de tu plugin. + +#### Registro en Init.php +```php +namespace FacturaScripts\Plugins\MiPlugin; + +use FacturaScripts\Core\Kernel; +use FacturaScripts\Core\Controller\ApiRoot; +use FacturaScripts\Core\Template\InitClass; + +class Init extends InitClass +{ + public function init(): void + { + Kernel::addRoute('/api/3/pruebas', 'ApiControllerPruebas', -1); + ApiRoot::addCustomResource('pruebas'); + } + // ... +} +``` + +#### Ejemplo de ApiController +```php +namespace FacturaScripts\Plugins\MiPlugin\Controller; + +use FacturaScripts\Core\Template\ApiController; + +class ApiControllerMiAccion extends ApiController +{ + public function runResource(): void + { + // Tu lógica aquí + $this->response->json(['ok' => 'Acción ejecutada']); + } +} +``` + +## Filtrado y paginación (en APIModel) + +Cuando se consultan modelos automáticos, se pueden usar parámetros en la URL: +- `limit`: Número de resultados (por defecto 50). +- `offset`: Desplazamiento para paginación. +- `filter[campo]`: Filtrar por un campo (ej: `filter[codcliente]=1`). +- `filter[campo_gt]`, `filter[campo_lt]`, `filter[campo_gte]`, `filter[campo_lte]`, `filter[campo_neq]`, `filter[campo_like]`: Operadores de comparación. +- `sort[campo]`: Ordenar por campo (`asc` o `desc`). + +## Respuestas + +La API responde siempre con un objeto JSON. + +### Éxito (200 OK) +```json +{ + "ok": "Mensaje informativo", + "data": { ... } +} +``` + +### Error (400 Bad Request, 401 Unauthorized, etc.) +```json +{ + "error": "Descripción del error", + "data": { ... } +} +``` diff --git a/ai/skills/extensions-and-hooks.md b/ai/skills/extensions-and-hooks.md new file mode 100644 index 0000000000..e759e7b972 --- /dev/null +++ b/ai/skills/extensions-and-hooks.md @@ -0,0 +1,99 @@ +# Extensiones y Ganchos (Pipes y Hooks) + +FacturaScripts permite extender la funcionalidad del sistema sin modificar el código del núcleo mediante **Extensiones** +(en PHP) y **Ganchos** (en plantillas Twig). Esta es la forma preferida de personalización antes que la herencia. + +## Extensiones (Backend PHP) + +Las extensiones se gestionan mediante el trait `FacturaScripts\Core\Template\ExtensionsTrait`, que es utilizado por +controladores y modelos. + +### Cómo funcionan las extensiones (`pipe`) + +En el código del núcleo, existen llamadas a `$this->pipe('nombre_del_evento', ...$argumentos)`. Los plugins pueden +registrar funciones que se ejecutan en estos puntos. + +- **`pipe(string $name, ...$arguments)`**: Ejecuta las extensiones registradas para ese nombre. Si una extensión + devuelve un valor distinto de `null`, se detiene la ejecución y se devuelve ese valor. +- **`pipeFalse(string $name, ...$arguments)`**: Ejecuta las extensiones hasta que una devuelva `false`. Si alguna + devuelve `false`, el método devuelve `false`. Si todas devuelven algo distinto de `false`, devuelve `true`. + +### Ejemplo de uso en un Controlador (Núcleo) + +```php +public function createViews(): void +{ + // ... lógica para crear vistas + $this->pipe('createViews'); +} +``` + +### Cómo registrar una extensión desde un Plugin + +En el código del núcleo, añade `$this->pipe('nombre_del_pipe')` donde quieras dar soporte a que otros plugins puedan +añadir contenido en ese pipe. Adicionalmente, puedes añadir variables después del nombre del pipe. + +```php +$this->pipe('nombre_del_pipe', $data); +``` + +### Registro de extensiones en Init.php + +Todas las extensiones deben registrarse en el archivo `Init.php` de la raíz del plugin para que FacturaScripts las +reconozca al cargar el plugin. + +```php +namespace FacturaScripts\Plugins\MiNuevoPlugin; + +use FacturaScripts\Core\Template\InitClass; + +class Init extends InitClass +{ + public function init(): void + { + // Registrar extensión de Modelo + $this->loadExtension(new Extension\Model\Cliente()); + + // Registrar extensión de Controlador + $this->loadExtension(new Extension\Controller\ListCliente()); + } +} +``` + +--- + +## Ganchos (Frontend Twig) + +Los ganchos (hooks) permiten a los plugins añadir contenido HTML en lugares específicos de las plantillas del núcleo sin +sobrescribir el archivo `.html.twig` completo. + +### Cómo funcionan los ganchos + +En las plantillas Twig, se encuentran llamadas a ganchos que los plugins pueden aprovechar para inyectar código. + +### Ejemplo de uso en Twig (Núcleo) + +```twig +{# En alguna plantilla del núcleo #} +{% for includeView in getIncludeViews('MenuTemplate', 'HeadFirst') %} + {% include includeView['path'] %} + {% endfor %} +``` + +### Cómo usar un gancho desde un Plugin + +Los plugins pueden registrar contenido para estos ganchos, lo que permite añadir campos a formularios, botones +adicionales o información extra en listados. + +Crear el archivo dentro de `Extension/View/MenuTemplate_HeadFirst.html.twig` para añadir código al archivo y posición +indicada en el propio nombre del archivo, donde `MenuTemplate` es el archivo y `HeadFirst` es la posición. + +--- + +## Reglas de Oro + +1. **Prioridad**: Usa siempre extensiones/pipes si existen antes que recurrir a la herencia de clases. +2. **No invasivo**: Las extensiones permiten que múltiples plugins interactúen con la misma parte del sistema sin + conflictos. +3. **Pipes de retorno**: Si un pipe debe devolver un valor (ej: un cálculo), asegúrate de conocer qué espera el núcleo. +4. **Ganchos de Twig**: Úsalos para añadir elementos visuales, scripts o estilos específicos en una vista. diff --git a/ai/skills/model-management.md b/ai/skills/model-management.md new file mode 100644 index 0000000000..d79418fee0 --- /dev/null +++ b/ai/skills/model-management.md @@ -0,0 +1,62 @@ +# Skill: Gestión de Modelos (ModelClass) + +Esta skill describe cómo trabajar con modelos de datos en FacturaScripts utilizando la clase base `ModelClass`. + +## Cuándo usar +- Realizar operaciones CRUD (Crear, Leer, Actualizar, Borrar). +- Buscar registros en la base de datos. +- Obtener totales o conteos de registros. +- Gestionar la persistencia de datos de forma segura. + +## Reglas +- Todos los modelos deben extender de `ModelClass` (o `ModelCore` indirectamente). +- Usar el método `save()` para insertar o actualizar registros. FacturaScripts detecta automáticamente si el registro existe. +- Los modelos representan tablas de la base de datos. +- No escribir consultas SQL manuales si el modelo puede resolverlo. + +## Ejemplos de uso + +### Obtener un registro por su clave primaria +```php +$user = new User(); +if ($user->load('admin')) { + echo "Usuario encontrado: " . $user->nick; +} +``` + +### Buscar múltiples registros +```php +// all(where, order, offset, limit) +$activeUsers = User::all([Where::eq('enabled', true)], ['nick' => 'ASC'], 0, 10); + +foreach ($activeUsers as $user) { + echo $user->nick; +} +``` + +### Crear y guardar un nuevo registro +```php +$user = new User(); +$user->nick = 'nuevo_usuario'; +$user->password = password_hash('secreto', PASSWORD_DEFAULT); +$user->email = 'nuevo@ejemplo.com'; +$user->enabled = true; + +if ($user->save()) { + echo "Usuario guardado correctamente."; +} +``` + +### Contar registros con condiciones +```php +$totalAdmins = User::count([Where::eq('admin', true)]); +echo "Total de administradores: " . $totalAdmins; +``` + +### Eliminar un registro +```php +$user = new User(); +if ($user->load('usuario_a_borrar')) { + $user->delete(); +} +``` diff --git a/ai/skills/plugin-development.md b/ai/skills/plugin-development.md new file mode 100644 index 0000000000..5ef9c861de --- /dev/null +++ b/ai/skills/plugin-development.md @@ -0,0 +1,115 @@ +# Skill: Extensión mediante Plugins + +Esta skill describe cómo extender FacturaScripts mediante la creación o modificación de plugins, siguiendo la arquitectura modular del sistema. + +## Cuándo usar +- Añadir nuevas funcionalidades sin modificar el código del núcleo (`Core`). +- Modificar el comportamiento de modelos o controladores existentes. +- Añadir nuevos modelos, controladores, vistas o tablas. + +## Reglas +- Los plugins se ubican en la carpeta `Plugins/`. +- Cada plugin tiene su propia estructura de carpetas similar al núcleo (`Controller/`, `Model/`, `Table/`, `XMLView/`, `Translation/`). +- Se debe preferir el uso de extensiones (`Extending models/controllers`) antes que la herencia directa. +- El archivo `facturascripts.ini` en la raíz del plugin define sus metadatos. + +## Estructura de un plugin +```text +Plugins/MiNuevoPlugin/ +├── facturascripts.ini (Metadatos del plugin) +├── Init.php (Registro de extensiones y lógica de arranque) +├── Controller/ (Controladores propios) +├── Model/ (Modelos propios) +├── Table/ (Definición de tablas) +├── XMLView/ (Definición de vistas) +├── Translation/ (Traducciones .json) +├── Extension/ (Extensiones de lógica del Core) +│ ├── Controller/ (Extender controladores existentes) +│ └── Model/ (Extender modelos existentes) +└── View/ (Plantillas Twig personalizadas) +``` + +## Ejemplo de uso + +### Archivo facturascripts.ini +```ini +name = 'MiNuevoPlugin' +description = 'Descripción de mi plugin' +version = 1.0 +author = 'MiNombre' +``` + +### Registro de extensiones en Init.php +Todas las extensiones de modelos y controladores deben registrarse en el archivo `Init.php` de la raíz del plugin para que el sistema las reconozca al cargar el plugin. + +```php +namespace FacturaScripts\Plugins\MiNuevoPlugin; + +use FacturaScripts\Core\Controller\ApiRoot; +use FacturaScripts\Core\Kernel; +use FacturaScripts\Core\Template\InitClass; + +class Init extends InitClass +{ + public function init(): void + { + // Registrar extensión de Modelo + $this->loadExtension(new Extension\Model\Cliente()); + + // Registrar extensión de Controlador + $this->loadExtension(new Extension\Controller\ListCliente()); + + // Registrar endpoint personalizado de la API (si aplica) + Kernel::addRoute('/api/3/miAccion', 'ApiControllerMiAccion'); + ApiRoot::addCustomResource('miAccion'); + } + + public function uninstall(): void + { + // Lógica al desinstalar el plugin + } + + public function update(): void + { + // Lógica de actualización si es necesaria + } +} +``` + +### Extender un Modelo del núcleo +Para añadir lógica a un modelo existente (ej: `Cliente`), se crea un archivo en `Plugins/MiNuevoPlugin/Extension/Model/Cliente.php`: + +```php +namespace FacturaScripts\Plugins\MiNuevoPlugin\Extension\Model; + +use Closure; + +class Cliente +{ + public function customMethod(): Closure + { + return function () { + return "Lógica añadida al modelo Cliente"; + }; + } +} +``` + +### Extender un Controlador del núcleo +Para añadir acciones o cambiar el comportamiento de una página: + +```php +namespace FacturaScripts\Plugins\MiNuevoPlugin\Extension\Controller; + +use Closure; + +class ListCliente +{ + public function createViews(): Closure + { + return function () { + return "Lógica añadida al controlador ListCliente"; + }; + } +} +``` diff --git a/ai/skills/table-definition.md b/ai/skills/table-definition.md new file mode 100644 index 0000000000..1090d72338 --- /dev/null +++ b/ai/skills/table-definition.md @@ -0,0 +1,62 @@ +# Skill: Definición de Tablas (XML) + +Esta skill describe cómo definir la estructura de las tablas de la base de datos mediante archivos XML en FacturaScripts. + +## Cuándo usar +- Crear nuevas tablas en el sistema o en un plugin. +- Añadir o modificar columnas en tablas existentes. +- Definir claves primarias y relaciones (claves foráneas). + +## Reglas +- Los archivos de tablas deben ubicarse en la carpeta `Table/` del núcleo o del plugin. +- FacturaScripts detecta automáticamente los cambios en estos archivos y sincroniza la base de datos (siempre que el modo desarrollador esté activo o se fuerce la actualización). +- El nombre del archivo debe coincidir con el nombre de la tabla. +- El nombre de la tabla siempre debe ser en minúsculas, sin espacios y en plural. +- El nombre de las columnas siempre debe ser en minúsculas, en singular y guion bajo en vez de espacios. + +## Estructura XML + +### Etiquetas principales +- ``: Nodo raíz que contiene la definición de la tabla. +- ``: Define una columna de la tabla. + - ``: Nombre de la columna. + - ``: Tipo de dato (ej: `integer`, `boolean`, `character varying(50)`, `timestamp`, `double precision`). + - ``: `NO` para columnas obligatorias, `YES` para opcionales (por defecto). + - ``: Valor por defecto para la columna. +- ``: Define restricciones como claves primarias o foráneas. + +## Ejemplo de uso + +### Definición de una tabla básica (`mi_tablas.xml`) +```xml + +
+ + id + integer + NO + + + nombre + character varying(100) + NO + + + fecha_creacion + timestamp + CURRENT_TIMESTAMP + + + mi_tablas_pkey + PRIMARY KEY (id) + +
+``` + +### Definición de una clave foránea +```xml + + ca_mi_tablas_cliente + FOREIGN KEY (codcliente) REFERENCES clientes (codcliente) ON DELETE CASCADE ON UPDATE CASCADE + +``` diff --git a/ai/skills/use-http.md b/ai/skills/use-http.md new file mode 100644 index 0000000000..2ecee630ad --- /dev/null +++ b/ai/skills/use-http.md @@ -0,0 +1,66 @@ +# Uso de la clase Http en FacturaScripts + +La clase `FacturaScripts\Core\Http` es una utilidad que envuelve cURL para realizar peticiones HTTP externas de forma sencilla y orientada a objetos. + +## Peticiones GET + +```php +use FacturaScripts\Core\Http; + +$response = Http::get('https://api.ejemplo.com/datos', ['param' => 'valor']); + +if ($response->ok()) { + $body = $response->body(); +} +``` + +## Peticiones POST y Envío de JSON + +```php +use FacturaScripts\Core\Http; + +$data = ['nombre' => 'Juan', 'email' => 'juan@ejemplo.com']; + +// POST normal +$response = Http::post('https://api.ejemplo.com/usuarios', $data); + +// POST JSON (envía los datos como cuerpo JSON y añade la cabecera Content-Type correspondiente) +$response = Http::postJson('https://api.ejemplo.com/usuarios', $data); + +if ($response->ok()) { + $result = $response->json(); // devuelve un array asociativo por defecto (u objeto si se pasa false) +} +``` + +## Otros Métodos + +- `put(url, data)`: Petición PUT. +- `patch(url, data)`: Petición PATCH. +- `delete(url, data)`: Petición DELETE. + +## Configuración de la Petición + +Se pueden encadenar métodos para configurar la petición antes de ejecutarla (aunque `get`, `post`, etc., la ejecutan inmediatamente, se pueden configurar cabeceras previamente). + +```php +$response = Http::post('https://api.ejemplo.com', $data) + ->setBearerToken('token123') + ->setTimeout(10) + ->setUserAgent('MiApp/1.0'); +``` + +### Autenticación Común + +- `setToken(token)`: Añade cabecera `Authorization: Token {token}`. +- `setBearerToken(token)`: Añade cabecera `Authorization: Bearer {token}`. +- `setUser(user, password)`: Añade autenticación básica HTTP. + +## Manejo de la Respuesta + +- `ok()`: Devuelve `true` si el código de estado es 200-299. +- `failed()`: Devuelve `true` si no es `ok()`. +- `status()`: Devuelve el código de estado HTTP (ej: 404, 500). +- `body()`: El cuerpo de la respuesta en crudo. +- `json(associative = false)`: Parsea el cuerpo como JSON (devuelve un array asociativo por defecto, u objeto si se pasa `false`). +- `errorMessage()`: Devuelve el mensaje de error de cURL si hubo fallo. +- `saveAs(filename)`: Guarda la respuesta directamente en un archivo (ideal para descargas). diff --git a/ai/skills/use-tools.md b/ai/skills/use-tools.md new file mode 100644 index 0000000000..277639a94f --- /dev/null +++ b/ai/skills/use-tools.md @@ -0,0 +1,63 @@ +# Skill: Uso de la clase Tools + +Esta skill describe cómo utilizar la clase `FacturaScripts\Core\Tools` para realizar operaciones comunes en el sistema. + +## Cuándo usar +- Formateo de fechas (`date`, `dateTime`). +- Formateo de números y dinero (`number`, `money`). +- Operaciones con carpetas (`folder`, `folderCheckOrCreate`, `folderCopy`). +- Acceso a configuraciones y ajustes (`config`, `settings`). +- Generación de strings aleatorios o contraseñas. +- Obtención de la URL del sitio. + +## Reglas +- La clase `Tools` es estática, se debe llamar como `Tools::metodo()`. +- Siempre que se necesite formatear una fecha para mostrar al usuario, usar `Tools::date()` o `Tools::dateTime()`. +- Para redondear importes, usar `Tools::round()`. +- Para traducciones rápidas desde `Tools`, usar `Tools::trans()`. + +## Ejemplos de uso + +### Formatear dinero +```php +use FacturaScripts\Core\Tools; + +// Formatea 123.45 con la divisa 'EUR' +echo Tools::money(123.45, 'EUR'); +``` + +### Obtener una configuración +```php +use FacturaScripts\Core\Tools; + +// Obtiene el valor de 'base_url' en el config.php, o 'http://localhost' por defecto +$url = Tools::config('base_url', 'http://localhost'); +``` + +### Manejo de fechas +```php +use FacturaScripts\Core\Tools; + +// Formatea la fecha actual para mostrar al usuario +echo Tools::date(date('Y-m-d')); + +// Sumar 1 mes a una fecha +$nextMonth = Tools::dateOperation(date('Y-m-d'), '+1 month'); +``` + +### Acceso a ajustes (Settings) +```php +use FacturaScripts\Core\Tools; + +// Obtener un ajuste de la base de datos (tabla settings) +$companyName = Tools::settings('default', 'company_name', 'Mi Empresa'); +``` + +### Guardar o actualizar ajustes (Settings) +```php +use FacturaScripts\Core\Tools; + +// Establecer un ajuste de la base de datos (tabla settings) +Tools::settingsSet('default', 'company_name', 'Mi Empresa 2'); +Tools::settingsSave(); +``` \ No newline at end of file diff --git a/ai/skills/use-translator.md b/ai/skills/use-translator.md new file mode 100644 index 0000000000..a9e45f1ecf --- /dev/null +++ b/ai/skills/use-translator.md @@ -0,0 +1,53 @@ +# Skill: Traducción e Internacionalización (Translator) + +Esta skill detalla cómo usar la clase `FacturaScripts\Core\Translator` para traducir textos y manejar idiomas. + +## Cuándo usar +- Traducir una cadena de texto a un idioma determinado. +- Consultar los idiomas instalados o disponibles. +- Cambiar el idioma de la sesión actual. +- Buscar claves de traducción. + +## Reglas +- Para traducciones rápidas dentro de controladores o modelos, usar `Tools::trans()`. +- Para obtener la instancia del traductor de un idioma específico, usar `Tools::lang('es_ES')`. +- Las traducciones se definen en archivos JSON dentro de `Core/Translation/` o en las carpetas `Translation/` de cada plugin. + +## Ejemplos de uso + +### Traducción simple con parámetros +```php +use FacturaScripts\Core\Tools; + +// Traduce la cadena y reemplaza %1 por el valor indicado +// Las claves de traducción suelen ser palabras en inglés +echo Tools::trans('order-number', ['%1' => '2025-001']); +``` + +### Usar una instancia de Translator directamente +```php +use FacturaScripts\Core\Tools; + +$traductor = Tools::lang('es_ES'); +echo $traductor->trans('save'); +``` + +### Consultar idiomas disponibles +```php +use FacturaScripts\Core\Tools; + +$traductor = Tools::lang(); +$idiomas = $traductor->getAvailableLanguages(); +foreach ($idiomas as $id => $nombre) { + echo "ID: $id, Nombre: $nombre"; +} +``` + +### Traducir a un idioma específico (sin cambiar el global) +```php +use FacturaScripts\Core\Tools; + +// Traduce 'invoice' al francés sin modificar el traductor global +$traductor = Tools::lang('fr_FR'); +echo $traductor->customTrans('invoice'); +``` diff --git a/ai/skills/xml-view-definition.md b/ai/skills/xml-view-definition.md new file mode 100644 index 0000000000..9c77298911 --- /dev/null +++ b/ai/skills/xml-view-definition.md @@ -0,0 +1,66 @@ +# Skill: Definición de Vistas (XMLView) + +Esta skill describe cómo definir de forma declarativa las vistas (listados y formularios) en FacturaScripts mediante archivos XML. + +## Cuándo usar +- Crear un nuevo listado de registros. +- Crear o modificar un formulario de edición o creación. +- Definir qué campos se muestran y qué widgets (controles) se usan. + +## Reglas +- Los archivos XML deben estar en la carpeta `XMLView/` del núcleo o del plugin. +- El nombre del archivo suele coincidir con el nombre del controlador que lo usa (ej: `EditProducto.xml`). +- Los widgets deben estar vinculados a nombres de campos del modelo (`fieldname`). + +## Estructura XML + +### Etiquetas principales +- ``: Nodo raíz. +- ``: Contenedor de las columnas o grupos de campos. +- ``: Agrupa campos visualmente. Permite definir el número de columnas de rejilla (`numcolumns`). +- ``: Define un campo en la vista. + - ``: Define el tipo de control (ej: `text`, `select`, `number`, `checkbox`, `date`, `password`, `textarea`). + +## Ejemplo de uso + +### Un formulario de edición simple (`EditAlgo.xml`) +```xml + + + + + + + + + + + + + + + + + + + + +``` + +### Un listado simple (`ListAlgo.xml`) +```xml + + + + + + + + + + + + + + +```