shoc-backend/docs/work-orders/phase-3/README.md

174 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Fase 3 — Criação e Cancelamento
**Programa:** Work Orders Board
**Objetivo:** Criação wizard/inline via contrato do board SHOC, cancelamento soft dedicado, ManualEditFlag na criação, e delete físico restrito a Admin.
**Depende de:** [Fase 0](../phase-0/README.md), [Fase 1](../phase-1/README.md), [Fase 2](../phase-2/README.md)
---
## Endpoints
### `POST /api/workorders/board`
Cria uma WO com contrato alinhado ao board. Suporta wizard (payload completo) e inline row (subset mínimo).
**Autenticação:** Bearer JWT (`[Authorize]`)
**Request body:**
```json
{
"woNumber": "12345",
"workOrderType": "PM",
"siteCode": "BK5",
"assignTo": "dispatcher-guid",
"dueDate": "2026-07-01",
"scheduledDate": "2026-06-25",
"targetWeek": "2026-06-22",
"scheduleWeekOnly": false,
"vendorId": 5,
"apptDate": "2026-06-26",
"apptTime": "09:00 – 11:00",
"docStatus": "No",
"description": "Leak in break room",
"trade": "HVAC PM",
"locationId": 12,
"pocContactId": 3,
"pocNotes": "Call before arrival"
}
```
| Campo | Obrigatório | Descrição |
|-------|-------------|-----------|
| `workOrderType` | Sim | Enum `WorkOrderType` |
| `siteCode` | Sim | Código do site |
| `woNumber` | Não | Se omitido, auto-gera sequencial normalizado 11 dígitos |
| `scheduleWeekOnly` | Não | Se `true`, `targetWeek` é obrigatório |
| `vendorId` | Condicional | Obrigatório quando `apptDate` ou `apptTime` informados |
**Responses:**
| HTTP | Body | Quando |
|------|------|--------|
| 200 | `WorkOrderBoardRowDto` | Sucesso — row pronto para inserir no board |
| 400 | `Response` | Validação FluentValidation |
| 409 | `WorkOrderBoardValidationErrorDto` | WO# duplicado |
| 422 | `WorkOrderBoardValidationErrorDto` | Regra de domínio |
**Exemplo (inline mínimo):**
```bash
curl -X POST -H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"workOrderType":"PM","siteCode":"BK5"}' \
"https://localhost:5001/api/workorders/board"
```
---
### `POST /api/workorders/{id}/cancel`
Soft cancel — transição para `LifecycleStatus.Canceled` com WO read-only.
**Autenticação:** Bearer JWT
**Responses:**
| HTTP | Body | Quando |
|------|------|--------|
| 200 | `WorkOrderBoardRowDto` | Cancelado (ou já estava cancelado — idempotente) |
| 422 | `WorkOrderBoardValidationErrorDto` | WO `Complete` ou `Closed` |
**Exemplo:**
```bash
curl -X POST -H "Authorization: Bearer <token>" \
"https://localhost:5001/api/workorders/42/cancel"
```
---
## Regras de domínio na criação
| Regra | Comportamento |
|-------|---------------|
| Status inicial | `Incomplete` |
| Auto-schedule | `scheduledDate` + `assignTo` → `Scheduled` |
| Set-once tracking | Primeira `scheduledDate` → `OriginalDate` / `OriginalWeek` |
| Week-only | `scheduleWeekOnly=true` + `targetWeek` → aparece na semana no GET board |
| WO# | Manual normalizado 11 dígitos; auto-gerado se omitido |
| Vendor | Cria dispatch primário quando `vendorId` informado |
| ManualEditFlag | Field locks criados para cada campo SHOC preenchido |
---
## Soft cancel vs hard delete
| Operação | Endpoint | Quem | Efeito |
|----------|----------|------|--------|
| Soft cancel | `POST /{id}/cancel` | Dispatcher | Status `Canceled`, WO permanece, PATCH bloqueado (422) |
| Hard delete | `DELETE DeleteWorkorder` | **Admin only** | Remove registro, anexos e contatos |
O legado `POST AddWorkorder` (form/Blazor) permanece inalterado.
---
## ManualEditFlag na criação
Campos preenchidos na criação SHOC recebem lock em `WorkOrderFieldLocks` via audit `FieldChanged`. Sync subsequente em campo lockado gera `SyncRejected` (ver [manual-edit-flag-design.md](../phase-0/manual-edit-flag-design.md)).
WO criada via Sync/Lambda continua sem locks até edição SHOC.
---
## Audit
| Evento | Action |
|--------|--------|
| Criação | 1× `Create` + `FieldChanged` por campo preenchido |
| Auto-schedule na criação | `StatusChanged` adicional |
| Cancel | `StatusChanged` → `Canceled` |
| Hard delete Admin | `Delete` |
---
## Código entregue
| Camada | Arquivo |
|--------|---------|
| DTOs | `SeaHaven.Services/DTOs/WorkOrderBoardDTOs.cs` |
| Validação | `SeaHaven.Services/Validation/WorkOrderBoardCreateValidation.cs` |
| Scheduling compartilhado | `SeaHaven.Services/Helpers/WorkOrderBoardFieldMutations.cs` |
| Create service | `SeaHaven.Services/Implementation/WorkOrderBoardCreateService.cs` |
| Cancel service | `SeaHaven.Services/Implementation/WorkOrderBoardCancelService.cs` |
| Audit | `IWorkOrderAuditService.StageCreated`, `LogCreatedAsync` |
| API | `WorkOrderController` — `POST board`, `POST {id}/cancel`, `DELETE` Admin |
| Testes | `WorkOrderBoardCreateServiceTests`, `WorkOrderBoardCancelServiceTests`, `WorkOrderBoardCreateSyncLockTests` |
---
## Gates de aceite
### Desenvolvimento
- [x] `POST /api/workorders/board` — Incomplete / auto-schedule / week-only
- [x] WO# auto ou manual 11 dígitos + unicidade (409)
- [x] Vendor/dispatch primário na criação
- [x] Field locks + SyncRejected pós-create SHOC
- [x] `POST /{id}/cancel` idempotente; PATCH bloqueado após cancel
- [x] `DELETE DeleteWorkorder` restrito a Admin
- [x] Legado `AddWorkorder` inalterado
- [x] 68 testes unitários total (17 Fase 3 + 51 Fases 0–2)
### Staging (pendente)
- [ ] UAT dispatcher: wizard + inline row
- [ ] Smoke Sync durante criação SHOC
- [ ] Confirmar navegação FE para semana do WO criado
---
## Próximo passo
**Fase 4** — Busca contextual na semana + advanced search cross-week conforme tier volume.