REF-901-03: Jira SLA Integration
ADR: ADR-901 — IntegrationsEscopo: Jira aplica SLAs, Plugin exibe, webhook flow, REST API sync, responsabilidade por dado, plugin NÃO roda relógio próprio
1. Princípio Central
Jira APLICA SLAs (motor nativo). Plugin EXIBE status no portal e agrega dados para relatórios.
Plugin NÃO roda relógio de SLA próprio. Razões:
- Jira já faz isso — motor de SLA lida com pausa/retomada, calendários, feriados
- Relógios paralelos criam drift (discrepâncias)
- Calendários de feriados e horário de verão precisam de fonte única
- Equipe mínima não consegue manter dois motores de SLA
2. Webhook Flow
Jira Service Management
│
├── Webhook: issue_created
│ └── Plugin: cria ServiceRequest (espelho)
│ ├── Preenche: jira_issue_key, priority, status
│ └── Inicia: sla_target baseado em support_class do Entitlement
│
├── Webhook: issue_updated
│ └── Plugin: atualiza SR
│ ├── Status sincronizado
│ ├── Campos SLA atualizados (sla_elapsed, sla_status)
│ └── Prioridade reclassificada (se equipe alterou)
│
├── Webhook: sla_breached
│ └── Plugin: marca SR como violada
│ ├── sla_status → breached
│ └── sla_breach_log atualizado
│
└── Webhook: issue_resolved / issue_closed
└── Plugin: SR → completed / closed
└── UST real preenchida (se aplicável)3. REST API Sync Periódico
Cron do plugin reconcilia dados com Jira via REST API:
| Frequência | O Que Faz |
|---|---|
| A cada 15 min | Busca SRs com status divergente (Jira vs Plugin) |
| Diário | Reconcilia campos SLA de todas as SRs abertas |
| Semanal | Gera relatório de conformidade de SLA |
Trata webhooks perdidos (Jira fora, webhook falhou, etc.).
4. Responsabilidade por Dado
| Dado | Source of Truth | Sync | Notas |
|---|---|---|---|
| Status da OS | Jira | Jira → Plugin | Jira vence para workflow |
| Prioridade | Jira | Jira → Plugin | Equipe define na triagem |
| Campos SLA (elapsed) | Jira | Jira → Plugin | Motor de SLA roda no Jira |
| SLA breached | Jira | Jira → Plugin | Plugin espelha estado |
| UST estimada | Plugin | Plugin → Jira | Plugin define, Jira lê via campo custom |
| UST real | Plugin | Calculado | Worklogs Jira + complexidade |
| Valor faturado | Plugin | N/A | Plugin é autoridade única de billing |
| Tipo de serviço | Plugin | Plugin → Jira | Catálogo do plugin |
| Tarefas / subtarefas | Jira | N/A | Plugin não replica gestão de projeto |
5. Modelo de Dados SLA no Plugin
ServiceRequest
├── jira_issue_key: "PROJ-123"
├── priority: P1 | P2 | P3 | P4 | P5
├── sla_started_at: datetime
├── sla_paused_at: datetime | null
├── sla_elapsed: int (seconds, do Jira)
├── sla_target: int (seconds, derivado de support_class × priority)
├── sla_calendar: "24/7" | "BH" (derivado da matrix)
├── sla_status: "on_track" | "at_risk" | "breached" (computed)
└── sla_breach_log: [
{ metric: "first_response", breached_at: datetime, target: 3600, actual: 4200 }
]6. Exibição no Portal
SR-20260042 — "Página de login retornando erro 500"
Prioridade: P2 Urgente
Classe: Business
Status do SLA:
┌──────────────────────────────────────────────────┐
│ Primeira Resposta [====........] 48min / 2h ✅ │
│ Resolução [==..........] 48min / 8h ✅ │
└──────────────────────────────────────────────────┘Cores: on_track (verde) → at_risk (amarelo, 80%+) → breached (vermelho).
7. Dashboard Admin
| Visualização | Conteúdo |
|---|---|
| Visão Geral SLA | % conformidade por classe no mês corrente |
| Itens Violados | SRs com SLA violado, por prioridade |
| Itens em Risco | SRs em 80%+ da meta, não violadas |
| Resumo por Org | Performance SLA por organization nos últimos 30/60/90 dias |
8. Escopo de Versão
| Funcionalidade | v5.0 | v5.0.x |
|---|---|---|
| SR criada via webhook Jira | Básico | Completo |
| Status sincronizado | Básico | Bidirecional |
| SLA exibido no portal | Estático | Tempo real |
| Worklogs → UST real | — | ✅ |
| Relatórios de conformidade SLA | — | ✅ |
| Criação de projeto Jira automática | — | ✅ |
9. Plugin→Jira: CRUD Integration
Além do fluxo Jira→Plugin (seções 1-8), o plugin também CRIA e GERENCIA issues no Jira.
Namespace
Middag\Account\Integration\Jira\
├── JiraClientInterface # Port: contrato HTTP (get/post/put/delete/upload)
├── JiraClient # Adapter: Guzzle, Basic Auth, retry on 429
├── JiraIssueService # Issues CRUD + transitions + search + createFromOrder()
├── JiraProjectService # Projects + issue types listing
├── JiraCommentService # Comments CRUD
├── JiraAttachmentService # Upload/delete attachments (multipart)
├── JiraWorklogService # Worklogs CRUD
├── AdfBuilder # Fluent builder para Atlassian Document Format (API v3)
├── DTO/
│ ├── JiraIssueDTO
│ ├── JiraProjectDTO
│ ├── JiraIssueTypeDTO
│ ├── JiraTransitionDTO
│ └── JiraCommentDTO
└── Exception/
├── JiraApiException
└── JiraRateLimitExceptionTodos os Services e Client têm sufixos auto-registráveis pelo ServiceProvider (auto-discovery). JiraClientInterface fica em Integration\Jira\ (não em Contract\ — seria ignorada pelo scanner). Auto-alias: Container::get(JiraClientInterface::class) → JiraClient.
10. JiraClient — HTTP Layer
- Base URL:
https://{JIRA_DOMAIN}.atlassian.net/rest/api/3 - Auth: Basic (
{JIRA_EMAIL}:{JIRA_API_TOKEN}) - Timeout: 30s
- Rate limiting: retry on HTTP 429 com
Retry-Afterheader, máximo 3 tentativas - Operações:
get(),post(),put(),delete(),upload()(multipart para attachments)
Env Vars
| Variável | Exemplo | Obrigatório |
|---|---|---|
JIRA_DOMAIN | middag | Sim |
JIRA_EMAIL | integrations@middag.com.br | Sim |
JIRA_API_TOKEN | ATATT3xFfGF0... | Sim |
Graceful Degradation
Se env vars ausentes: JiraClient inoperante — todos os métodos lançam JiraApiException. Consumers (hooks, controllers) capturam exception e logam warning. Sistema funciona normalmente sem Jira. Mesmo pattern do code-intel (integração opcional).
11. Order→Jira Automation
Trigger
woocommerce_order_status_completed → JiraOrderHooks::onOrderCompleted()
Localização: Middag\Account\WordPress\Hook\JiraOrderHooks (auto-discovered pelo HookRegistrar).
Flow
- Hook recebe
$orderId - Para cada item do pedido, verifica se produto tem
_middag_jira_enabled = yes - Se sim, lê config Jira do produto (project_key, issue_type_id)
- Chama
JiraIssueService::createFromOrder()com dados do pedido AdfBuildergera description em formato ADF (heading, dados cliente, itens, total)- Issue criada →
issue.keysalvo como order meta_middag_jira_issue_{item_id} - Falha: log warning, não bloqueia pedido
Product Meta Keys
| Key | Tipo | Obrigatório |
|---|---|---|
_middag_jira_enabled | yes/no | Sim |
_middag_jira_project_key | string (ex: MIDDAG) | Sim (se enabled) |
_middag_jira_issue_type_id | string (ex: 10001) | Sim (se enabled) |
_middag_jira_summary_template | string (ex: Onboarding: {billing_name}) | Não |
Pattern idêntico ao _middag_nfse_* — consistência com mapeamentos existentes.
12. REST API Endpoints (Admin + Portal)
Controller: Middag\Account\Api\V1\JiraController (scope = 'jira')
| Método | Endpoint | Descrição |
|---|---|---|
| GET | middag-account/v1/jira/projects | Lista projetos Jira |
| GET | middag-account/v1/jira/projects/{key}/issue-types | Issue types de um projeto |
| POST | middag-account/v1/jira/issues | Cria issue |
| GET | middag-account/v1/jira/issues/{key} | Busca issue por key |
| PUT | middag-account/v1/jira/issues/{key} | Atualiza issue |
| GET | middag-account/v1/jira/issues/search?jql=... | Busca JQL |
| POST | middag-account/v1/jira/issues/{key}/transitions | Transiciona issue |
| POST | middag-account/v1/jira/issues/{key}/comments | Adiciona comentário |
13. ADF Builder
API v3 do Jira exige Atlassian Document Format para descriptions e comments. AdfBuilder oferece fluent API: heading(), paragraph(), richParagraph(), bold(), link(), bulletList(), codeBlock(), divider(), toArray().
Usado por JiraIssueService::createFromOrder() para montar description estruturada com dados do pedido.
14. DI Container Registration
Nenhuma alteração em Container.php necessária. Auto-discovery resolve:
| Classe | Sufixo | Auto-registrado | Auto-alias |
|---|---|---|---|
| JiraClient | Client | Sim | → JiraClientInterface |
| JiraIssueService | Service | Sim | — |
| JiraProjectService | Service | Sim | — |
| JiraCommentService | Service | Sim | — |
| JiraAttachmentService | Service | Sim | — |
| JiraWorklogService | Service | Sim | — |
| AdfBuilder | Builder | Sim | — |
| JiraController | Controller | Sim | — |
| JiraOrderHooks | — | Não (HookRegistrar) | — |
15. Implementation Waves
Wave 1 — Fundação (sem WordPress deps):
JiraClientInterface, JiraClient, Exceptions, AdfBuilder, DTOs
Wave 2 — Services:
JiraProjectService, JiraIssueService, JiraCommentService,
JiraAttachmentService, JiraWorklogService
Wave 3 — WordPress integration:
JiraOrderHooks (automação pagamento), JiraController (API v1)
Wave 4 — Admin UI:
JiraProductHooks (campos Jira no editor de produto WC)