From c51827a57c4fd9eb777e3a0d24aca1e167f45fe8 Mon Sep 17 00:00:00 2001 From: Gemini Date: Fri, 10 Jul 2026 15:03:24 -0300 Subject: [PATCH] KB-PLUGIN-039: substrato nativo GLPI 11 de projetos/chamados reutilizavel (base do mindscrum) Mapeia o que o core ja entrega (Kanban trait single-itemtype, ProjectTaskLink com 4 tipos de precedencia, ProjectTask_Ticket, PlanningEvent + checkAlreadyPlanned, TeamworkInterface, Gantt como plugin) e a tabela herdar-vs-construir do plugin mindscrum. Co-Authored-By: Claude Opus 4.8 --- index.json | 25 +++- ...-039-glpi11-project-ticket-pm-substrate.md | 127 ++++++++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 records/plugin-dev/KB-PLUGIN-039-glpi11-project-ticket-pm-substrate.md diff --git a/index.json b/index.json index b5be877..87b728a 100755 --- a/index.json +++ b/index.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "last_updated": "2026-07-03", + "last_updated": "2026-07-10", "records": [ { "id": "KB-INFRA-001", @@ -740,6 +740,29 @@ "severity": "high", "path": "records/plugin-dev/KB-PLUGIN-038-glpi11-frontend-assets-monaco-public.md", "summary": "id: KB-PLUGIN-038" + }, + { + "id": "KB-PLUGIN-039", + "title": "\"GLPI 11 — Substrato nativo de gestão de projetos/chamados (Kanban, precedência, planning) reutilizável por plugin\"", + "domain": "plugin-dev", + "tags": [ + "glpi11", + "plugin", + "kanban", + "project", + "projecttask", + "ticket", + "planning", + "gantt", + "precedence", + "teamwork", + "mindscrum", + "architecture" + ], + "status": "active", + "severity": "high", + "path": "records/plugin-dev/KB-PLUGIN-039-glpi11-project-ticket-pm-substrate.md", + "summary": "id: KB-PLUGIN-039" } ] } diff --git a/records/plugin-dev/KB-PLUGIN-039-glpi11-project-ticket-pm-substrate.md b/records/plugin-dev/KB-PLUGIN-039-glpi11-project-ticket-pm-substrate.md new file mode 100644 index 0000000..a94b551 --- /dev/null +++ b/records/plugin-dev/KB-PLUGIN-039-glpi11-project-ticket-pm-substrate.md @@ -0,0 +1,127 @@ +--- +id: KB-PLUGIN-039 +title: "GLPI 11 — Substrato nativo de gestão de projetos/chamados (Kanban, precedência, planning) reutilizável por plugin" +domain: plugin-dev +tags: + - glpi11 + - plugin + - kanban + - project + - projecttask + - ticket + - planning + - gantt + - precedence + - teamwork + - mindscrum + - architecture +status: active +severity: high +created_at: 2026-07-10 +updated_at: 2026-07-10 +applies_to: + - GLPI 11.0.8 dev (container devportal_glpi) + - plugin mindscrum (Kanban unificado + Gantt de recursos) +related_records: + - KB-PLUGIN-028 + - KB-PLUGIN-029 + - KB-PLUGIN-031 + - KB-PLUGIN-036 +--- + +# GLPI 11 — Substrato nativo de gestão de projetos/chamados reutilizável por plugin + +Mapa do que o **core do GLPI 11 já entrega** para gestão de projetos, chamados, +tarefas, técnicos, precedência e agenda — levantado por leitura do código-fonte +em `/var/www/glpi/src/` (não é suposição; cada item foi verificado no fonte). +Base de decisão do plugin **mindscrum** (Kanban unificado + Gantt de recursos): +**herdar o motor, construir só as superfícies que faltam.** + +## Kanban nativo — trait + interface, single-itemtype + +- `Glpi\Features\Kanban` (trait) + `Glpi\Features\KanbanInterface` (contrato). +- **Quem implementa:** `Project` e `CommonITILObject` (`use Glpi\Features\Kanban; + implements KanbanInterface, TeamworkInterface`) → logo **Ticket, Change e Problem + já têm Kanban nativo**, além de Projeto. +- Cada board é de **um único itemtype**. Não há board multi-itemtype nativo. + → **Este é o gap que o mindscrum preenche** (juntar Ticket + ProjectTask numa tela). +- **Coluna = `column_field`:** `status` para ITIL (`getAllKanbanColumns('status')` + em `CommonITILObject`), `projectstates_id` para `Project`/`ProjectTask`. + Mover card grava o status/estado nativo — a regra de transição é do GLPI. +- Métodos-chave do contrato (`KanbanInterface`): `getDataToDisplayOnKanban`, + `getKanbanColumns`, `getAllKanbanColumns`, `showKanban`, `getAllForKanban`, + `canModifyGlobalState`, `prepareKanbanStateForUpdate` (hook para vetar/alterar + save), `canOrderKanbanCard`, e o ponto de extensão de plugin **`getKanbanPluginFilters($itemtype)`**. +- **Persistência do board:** `Item_Kanban::saveStateForItem($itemtype,$items_id,$state)` + / `loadStateForItem()` → tabela `glpi_items_kanbans` (state em JSON, por usuário + ou global). Passa por `prepareKanbanStateForUpdate()` antes de gravar. +- **UI reutilizável:** componente Twig `templates/components/kanban/kanban.html.twig` + + componente JS do Kanban do core. + +## Estados / colunas customizáveis + +- `ProjectState` (dropdown) é a lista de estados de projeto/task — **customizável**, + serve de coluna. Status de chamado é fixo (enum 1..6: novo, atrib., planejado, + pendente, resolvido, fechado). Reconciliar esses dois modelos numa coluna única é + o **miolo da regra** do board unificado. + +## Precedência entre tarefas (base de Gantt) — JÁ EXISTE + +- `ProjectTaskLink` → tabela `glpi_projecttasklinks`, campos + `projecttasks_id_source`, `projecttasks_id_target`, `type`. +- **4 tipos clássicos:** `finish_to_start=0`, `start_to_start=1`, + `finish_to_finish=2`, `start_to_finish=3`. É exatamente o modelo de dependência + de um Gantt — não precisa criar tabela nova para precedência. + +## Elo Projeto ↔ Chamado — JÁ EXISTE + +- `ProjectTask_Ticket` → tabela `glpi_projecttasks_tickets`, liga + `projecttasks_id` ↔ `tickets_id`. O relacionamento que o board unificado quer + representar já é modelado (e a classe já cruza `ProjectState`). + +## Planning / agenda / alocação — JÁ EXISTE + +- `ProjectTask` **é plannable:** `use Glpi\Features\PlanningEvent`, campos + `plan_start_date`/`plan_end_date` e `real_start_date`/`real_end_date`; implementa + `CalDAVCompatibleItemInterface` e `TeamworkInterface`. +- **Detecção de conflito de recurso:** `Planning::checkAlreadyPlanned($users_id, + $begin, $end)` já avisa quando um técnico é agendado em dobro — espinha dorsal da + visão "capacidade por técnico" do Gantt de recursos. +- Também plannable e alimentando o Planning: `TicketTask`, `ChangeTask`, + `ProblemTask`, `PlanningExternalEvent`, `Reminder`. + +## Equipe / técnicos — TeamworkInterface + +- `Glpi\Features\TeamworkInterface`: `getTeamRoles()`, `getTeamRoleName()`, + `getTeamItemtypes()`, `addTeamMember()`, `deleteTeamMember()`, `getTeam()`. +- Papéis via `Team::ROLE_*`: Projeto usa `ROLE_OWNER`/`ROLE_MEMBER`; ITIL usa + `ROLE_REQUESTER`/`ROLE_OBSERVER`/`ROLE_ASSIGNED`. Vínculo técnico↔tarefa via + `ProjectTaskTeam` / `ProjectTeam`. + +## Gantt nativo é PLUGIN, não core + +- O core apenas condiciona: `$plugin->isActivated('gantt')` e expõe o campo + `show_on_global_gantt`. O Gantt em si vem do plugin `gantt`. Ou seja, **estender + a gestão de projeto por plugin é o caminho oficial** — o mindscrum segue o mesmo + padrão, com foco em Gantt de *recursos* (por técnico), que o nativo não cobre. + +## Implicações para o mindscrum + +| Necessidade | Veredito | O que usar | +|---|---|---| +| Mover card muda status | herdar | `update()` nativo do itemtype (Ticket/ProjectTask) | +| Colunas = estados nativos | herdar | `status` (ITIL) / `ProjectState` | +| Precedência de tarefas | herdar | `ProjectTaskLink` (4 tipos) | +| Projeto ↔ chamado | herdar | `ProjectTask_Ticket` | +| Conflito de alocação | herdar | `Planning::checkAlreadyPlanned()` | +| Técnicos por tarefa | herdar | `TeamworkInterface` / `ProjectTaskTeam` | +| **Board multi-itemtype (Ticket+ProjectTask)** | **construir** | página full-screen do plugin (nativo é single-itemtype) | +| **Timeline de capacidade por técnico** | **construir** | consome Planning; render próprio | +| Chat/notas de execução no card | construir | tickets têm `ITILFollowup`; ProjectTask exige tabela auxiliar leve | + +## Regra para agentes + +Antes de recriar qualquer coisa de projeto/chamado/agenda no mindscrum, checar +esta tabela: quase tudo é **herança do core**, não desenvolvimento novo. Escrever +de volta sempre pelos models nativos (`->update()`), nunca `UPDATE` direto — assim +transição de status, histórico (`Log`) e regras do GLPI continuam válidos.