diff --git a/index.json b/index.json index f983cf7..310426d 100755 --- a/index.json +++ b/index.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "last_updated": "2026-07-02", + "last_updated": "2026-07-03", "records": [ { "id": "KB-INFRA-001", diff --git a/records/plugin-dev/KB-PLUGIN-037-redmine-plugin-api-contract.md b/records/plugin-dev/KB-PLUGIN-037-redmine-plugin-api-contract.md index 8bacc98..a891662 100644 --- a/records/plugin-dev/KB-PLUGIN-037-redmine-plugin-api-contract.md +++ b/records/plugin-dev/KB-PLUGIN-037-redmine-plugin-api-contract.md @@ -103,6 +103,33 @@ Escrita: `POST /projects.json` (criar projeto c/ custom fields), `POST /issues.j (issue do chamado), `PUT /issues/:id.json` (status), `POST /time_entries.json` (tempo), `POST /projects/:id/memberships.json` (auto-membership). +## Motor de Templates de Payload (2.0) + +A partir da **2.0** o corpo de cada operação (`create_issue`, `log_time`, +`update_status`, `create_project`) pode vir de um **template editável** em vez de +ser montado no código — o objetivo é o plugin virar **produto ambiente-agnóstico** +(cada Redmine tem seus campos obrigatórios/personalizados). Guia do usuário: +`docs/TEMPLATES.md`; contrato de dev: `docs/API.md`. + +- **`PluginRedmineTemplateengine`** (`inc/templateengine.class.php`): tabela + `glpi_plugin_redmine_templates`, renderizador **mustache-like** (`{{ var | filtro }}`; + tag ocupando o valor inteiro → **tipo nativo**; lookup indexado `map.status[chamado.status]`; + filtros `truncar/sem_html/minusculo/identificador/padrao`; `prune` de nulos), seeds + equivalentes ao 1.x, descoberta de custom fields e os contextos (`buildContext`, + `buildFormContext`, `sampleContext`). +- **Precedência**: template **ativo** → renderiza e envia; erro de **render** → log + + **fallback 1.x**; **sem** template ativo → comportamento **1.x idêntico**. Ou seja, + atualizar da 1.x para a 2.0 **não muda nada** até ativar um template. +- **UI** (config): editor linha-a-linha "DE → PARA" (paleta de variáveis GLPI via + autocomplete + dicionário dos campos que o Redmine espera, com obrigatoriedade e + valores), botão "Gerar template" (local, sem reload) e **testador** + (`ajax/template_test.php`): preview do render + dry-run que cria/apaga objeto de + teste e **traduz os 422** em dicas. +- **NÃO virou template** (é motor, não payload): impersonation, idempotência, + membership, gates (Feito/duração), recuperação de issue órfã. +- Decisão de escopo (2026-07-03): **não** implementar override por vínculo nem perfis + multi-Redmine sem caso real (YAGNI) — o template global cobre o cenário atual. + ## Gotchas de manutenção - Dev = GLPI 11.0.7, prod = **11.0.4**: desenvolver mirando 11.0.0+ (sem