docs: API.md — criação de projeto com custom_field_values e regras por instância

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Gemini 2026-07-02 10:42:11 -03:00
parent c8765ca5ff
commit 27ee6addeb

View file

@ -97,11 +97,12 @@ Sem vínculo (nem projeto nem entidade) → **nada é enviado** (log e retorno).
| GET | `/roles.json` | papéis (para auto-membership) |
| GET | `/users.json?limit=100&offset=N` | usuários (cache p/ mapeamento; paginado) |
| GET | `/projects/{id}/issue_categories.json` | categorias (por projeto) |
| GET | `/custom_fields.json` | definições de campos personalizados (filtra `customized_type=project`) |
### Escrita
| Método | Endpoint | Uso |
|---|---|---|
| POST | `/projects.json` | criar projeto Redmine (aba Projeto/Entidade) |
| POST | `/projects.json` | criar projeto Redmine (aba Projeto/Entidade) — inclui `custom_field_values` |
| POST | `/issues.json` | **criar a issue** a partir do chamado |
| PUT | `/issues/{id}.json` | sincronizar **status** da issue |
| POST | `/time_entries.json` | **lançar tempo** da TicketTask |
@ -138,10 +139,35 @@ Sem vínculo (nem projeto nem entidade) → **nada é enviado** (log e retorno).
|---|---|
| `status_id` | `config.status_map[Ticket.status]` (no `item_update` do Ticket) |
### Criação de projeto (`POST /projects.json` — abas Redmine de Projeto/Entidade)
| Campo Redmine (`project.*`) | Origem |
|---|---|
| `name`, `description`, `is_public` | formulário da aba |
| `identifier` | formulário, **normalizado para minúsculas** (regra do Redmine) |
| `parent_id` | dropdown "Subprojeto de" |
| `enabled_module_names` | multiselect "Módulos" |
| `custom_field_values` | `{ "<cf_id>": "<valor>", ... }` — campos personalizados de projeto |
Os campos personalizados são renderizados **dinamicamente** a partir de
`metadata_cache.project_custom_fields` (populado pelo "Sincronizar Metadados" via
`GET /custom_fields.json`). Em instâncias onde eles são **obrigatórios** (ex.:
produção Mindtek: "Tipo de Projeto" e "Tipo de Faturamento"), a criação falha com
422 se não forem enviados.
### Conversões importantes
- **Tempo:** GLPI grava `actiontime` em **segundos** (int); Redmine espera **horas decimais**. `5400 → 1.5`.
- **Subject:** limite de 255 chars no Redmine → truncado.
- **HTML:** descrições do GLPI (TinyMCE) passam por `RichText::getTextFromHtml`.
- **Identificador de projeto:** minúsculas/números/traços — normalizado em `createProjectFull()`.
### Regras que variam por instância/projeto do Redmine (validar em produção)
- **Custom fields de projeto** podem ser obrigatórios na criação (ver acima).
- **Atividade do time entry é por projeto**: a `default_activity_id` precisa estar
habilitada no projeto de destino (senão 422 "não está incluso na lista").
- **Comentário do time entry** pode ser obrigatório: task sem descrição usa o
fallback "Tempo lançado via GLPI (chamado #N)".
- **Tracker é por projeto**: default global vazio = Redmine usa o default do projeto.
- Issues só podem ser criadas em projetos **ativos** (o dropdown de vínculo já filtra).
---