# Fase 6 — Completion Doc e Slide-over **Programa:** Work Orders Board **Objetivo:** Contrato SHOC para slide-over (`WOSlideOver`): detalhe unificado, `docStatus` WO-level com templates por serviço, e tabs Comments/Audit/Media alinhadas ao frontend. **Depende de:** [Fase 0](../phase-0/README.md) … [Fase 5](../phase-5/README.md) --- ## Endpoints ### `GET /api/workorders/{id}/detail` Payload único para abrir o slide-over. **Autenticação:** Bearer JWT (`[Authorize]`) **Response:** ```json { "info": { /* WorkOrderDetailInfoDto — board row + description/trade/original* */ }, "completion": { "docStatus": "No", "template": { "id": 1, "name": "HVAC PM Completion", "serviceKey": "HVAC PM", "templateUrl": "..." }, "signOffName": null, "signOffAttachment": null, "signOffSignature": null, "dispatchSignoffs": [] }, "comments": [{ "id": 1, "authorId": "guid", "text": "...", "time": "2026-06-01T12:00:00.0000000Z" }], "audit": [{ "type": "manual", "dispatcherId": "guid", "action": "FieldChanged", "fieldName": "DocStatus", "oldValue": "No", "newValue": "Yes", "time": "..." }], "media": [{ "id": 5, "category": "Extra", "url": "...", "isLegacy": false }] } ``` ```bash curl -H "Authorization: Bearer " \ "https://localhost:5001/api/workorders/42/detail" ``` --- ### `GET /api/workorders/{id}/audit?limit=50` Audit tab lazy refresh. Schema FE: `{ type, dispatcherId?, action, fieldName?, oldValue, newValue, time, dispatchId? }`. --- ### `GET /api/workorders/{id}/comments` ### `POST /api/workorders/{id}/comments` ```json { "text": "Called vendor" } ``` Response: `{ id, authorId, text, time, documents? }`. --- ### Completion templates | Método | Rota | Auth | Descrição | |--------|------|------|-----------| | GET | `/api/workorders/completion-templates` | JWT | Query `serviceKey`, `workOrderType` | | GET | `/api/workorders/completion-templates/{id}` | JWT | Detalhe | | POST | `/api/workorders/completion-templates` | Admin | Criar template | | PUT | `/api/workorders/completion-templates/{id}` | Admin | Atualizar | | DELETE | `/api/workorders/completion-templates/{id}` | Admin | Soft delete | Lookup na WO: `Trade` → fallback `WorkOrderType`. --- ### `POST /api/workorders/{id}/completion-doc` Upload PDF preenchido (multipart). | Campo form | Obrigatório | |------------|-------------| | `file` | Sim | | `signOffName` | Não | | `signOffSignature` | Não | | `workOrderVersion` | Recomendado (Base64 RowVersion) | **Regras:** - WO read-only (`Canceled`/`Complete`/`Closed`) → 422 - Sucesso → `SignOffAttachment` + `DocStatus=Yes` + audit `FieldChanged` - Dispatch signoffs → somente leitura no slide-over ```bash curl -X POST -H "Authorization: Bearer " \ -F "file=@completion.pdf" \ -F "signOffName=Jane Doe" \ "https://localhost:5001/api/workorders/42/completion-doc" ``` **Inline toggle:** `PATCH /api/workorders/{id}/board` com `field=docStatus` (Fase 2). --- ### Media | Método | Rota | Descrição | |--------|------|-----------| | GET | `/api/workorders/{id}/media` | Lista unificada com `category` | | POST | `/api/workorders/{id}/media` | multipart: `category` (Before/After/Extra/Completion) + `file` | | DELETE | `/api/workorders/{id}/media/{mediaId}` | Soft delete (somente attachments com `id > 0`) | Legacy columns (`BeforPhotoAttachment`, `AfterPhotoAttachment`, `SignOffAttachment`) aparecem na projeção com `isLegacy: true`. --- ## Schema Migration `Phase6_CompletionSlideOver`: - Tabela `CompletionDocTemplates` - Coluna `Category` em `workOrderAttachments` - Backfill SQL: `SignOffAttachment` preenchido → `DocStatus=Yes` Script ops: [`scripts/backfill-docstatus.ps1`](../../scripts/backfill-docstatus.ps1) --- ## Código entregue | Camada | Arquivo | |--------|---------| | Model | `CompletionDocTemplate.cs`, `WorkOrderMediaCategory` enum | | Migration | `20260625120000_Phase6_CompletionSlideOver.cs` | | Data | `WorkOrderDetailDataService`, `CompletionDocTemplateDataService` | | Services | `WorkOrderDetailService`, `WorkOrderCommentService`, `WorkOrderCompletionService`, `WorkOrderMediaService` | | DTOs | `WorkOrderDetailDTOs.cs` | | Helpers | `WorkOrderAuditProjection`, `WorkOrderCommentProjection`, `WorkOrderMediaProjection` | | API | `WorkOrderController` — rotas `/detail`, `/comments`, `/audit`, `/completion-doc`, `/media`, `/completion-templates` | | Testes | `WorkOrderPhase6Tests.cs` | --- ## Critérios de aceite - [x] `GET /detail` retorna Info + Completion + Comments + Audit + Media no contrato FE - [x] Coluna COMP DOC do board via `docStatus` no `WorkOrderBoardRowDto` (Fase 1) - [x] `CompletionDocTemplate` CRUD admin + lookup por `serviceKey`/`workOrderType` - [x] `POST completion-doc` persiste attachment, define `DocStatus=Yes`, audit - [x] Comments/Audit tabs sem adapter no FE - [x] Media com `category`; legado mapeado - [x] Endpoints legados (`GetWorkorderById`, `GetCommentsByWorkorderId`) inalterados - [x] Testes: DocStatus PATCH, detail, completion upload, comments, media --- ## Fora de escopo - Geração de PDF server-side - Alteração Vendor Portal checklist/signoff - Rollout / sunset Blazor (Fase 7)