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

5.1 KiB

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 … Fase 5


Endpoints

GET /api/workorders/{id}/detail

Payload único para abrir o slide-over.

Autenticação: Bearer JWT ([Authorize])

Response:

{
  "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 }]
}
curl -H "Authorization: Bearer <token>" \
  "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

{ "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
curl -X POST -H "Authorization: Bearer <token>" \
  -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


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

  • GET /detail retorna Info + Completion + Comments + Audit + Media no contrato FE
  • Coluna COMP DOC do board via docStatus no WorkOrderBoardRowDto (Fase 1)
  • CompletionDocTemplate CRUD admin + lookup por serviceKey/workOrderType
  • POST completion-doc persiste attachment, define DocStatus=Yes, audit
  • Comments/Audit tabs sem adapter no FE
  • Media com category; legado mapeado
  • Endpoints legados (GetWorkorderById, GetCommentsByWorkorderId) inalterados
  • 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)