mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 22:23:12 +00:00
194 lines
5.4 KiB
Markdown
194 lines
5.4 KiB
Markdown
# ADR: Work Orders Board API (Fase 1 read-only)
|
|
|
|
**Status:** Proposed — spikes G0, G1, G3 concluídas
|
|
**Data:** 2026-06-19
|
|
**Deciders:** Backend + FE (aprovação Fase 1 pending)
|
|
|
|
---
|
|
|
|
## Contexto
|
|
|
|
O Schedule Board (FE) organiza work orders por `ScheduledDate` em visão semanal. O backend atual expõe `GetWorkOrderList` — listagem CRUD paginada sem janela temporal, sem `siteCode`, sem vendor inline, sem `ScheduledDate` na projeção.
|
|
|
|
Spikes de referência:
|
|
|
|
- [Consumer Audit](../spikes/consumer-audit-getworkorderlist.md)
|
|
- [WorkOrderType](../spikes/work-order-type.md)
|
|
- [Search Strategy](../spikes/search-strategy.md)
|
|
|
|
---
|
|
|
|
## Decisão
|
|
|
|
### 1. Endpoint dedicado (sem `projection=`)
|
|
|
|
Criar endpoint **separado** para o Schedule Board. **Não alterar** `GetWorkOrderList`.
|
|
|
|
```http
|
|
GET /api/workorders/GetWorkOrdersBoard
|
|
?scheduledFrom=2026-06-01
|
|
&scheduledTo=2026-06-07
|
|
&assignee=guid1&assignee=guid2
|
|
&search=BK5
|
|
&status=Open&status=InProgress
|
|
&locationId=42
|
|
```
|
|
|
|
Rota alias: `GET /api/WorkOrder/GetWorkOrdersBoard` (consistente com controller existente).
|
|
|
|
**Rejeitado:**
|
|
|
|
- `GET /api/workorders/table`
|
|
- `GET /GetWorkOrderList?projection=table`
|
|
|
|
### 2. Window-based fetch (sem paginação Fase 1)
|
|
|
|
| Abordagem | Fase 1 |
|
|
|-----------|--------|
|
|
| `scheduledFrom` + `scheduledTo` | **Obrigatório** |
|
|
| `page` / `pageSize` | **Ausente** |
|
|
| Limite janela | Max **90 dias** (validação server-side) |
|
|
|
|
Response envelope:
|
|
|
|
```json
|
|
{
|
|
"scheduledFrom": "2026-06-01",
|
|
"scheduledTo": "2026-06-07",
|
|
"totalCount": 42,
|
|
"items": [
|
|
{
|
|
"row": { /* WorkOrderBoardRowDto */ },
|
|
"presentation": { /* BoardRowPresentation */ }
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 3. DTO — domínio vs presentation
|
|
|
|
**`WorkOrderBoardRowDto`** — dados persistidos / joináveis:
|
|
|
|
```csharp
|
|
public record WorkOrderBoardRowDto(
|
|
int Id,
|
|
string? WoNumber,
|
|
string? SiteCode,
|
|
string? LocationLabel,
|
|
DateOnly? ScheduledDate,
|
|
TimeOnly? ScheduledStart,
|
|
DateOnly? DueDate,
|
|
string? WorkOrderType,
|
|
string? ServiceType,
|
|
string? AssigneeId,
|
|
string? AssigneeName,
|
|
string? VendorCompany,
|
|
string? VendorTechnician,
|
|
string Status,
|
|
string? PocName,
|
|
string? PocPhone
|
|
);
|
|
```
|
|
|
|
**`BoardRowPresentation`** — calculado no mapper backend:
|
|
|
|
```csharp
|
|
public record BoardRowPresentation(
|
|
string StatusDisplay,
|
|
bool IsPastDue,
|
|
string? WorkOrderTypeDisplay
|
|
);
|
|
```
|
|
|
|
Mapper: `IWorkOrderBoardMapper` centraliza Past Due e type display.
|
|
|
|
### 4. Query EF (Fase 1)
|
|
|
|
- Filtro base: `istemplate != true`
|
|
- Janela: `ScheduledDate >= from && ScheduledDate < to.AddDays(1)`
|
|
- Includes: `Locations`, `AssignToUser`, `Dispatches` → `Vendor` (1 vendor por WO — first active dispatch)
|
|
- POC: `WorkOrderContacts` (primary)
|
|
- Service type: `Trade` ou category join (mínimo: `Trade`)
|
|
- **Não incluir** subquery `lastUpdated` (Comments/AuditLog)
|
|
|
|
### 5. Search (conforme spike)
|
|
|
|
- Search scoped à janela temporal
|
|
- Servidor: `StartsWith` em `InternalWONumber`, `SiteCode`
|
|
- Count ≤ **300**: retornar semana inteira; FE filtra title/location/serviceType
|
|
- Count > 300: exigir termo indexável ou retornar 400
|
|
- Assignee: `assigneeId[]` multi — **não** filtrar por nome
|
|
|
|
Índices (migration separada pós-aprovação):
|
|
|
|
- `IX_workOrders_ScheduledDate` (P1)
|
|
- `IX_workOrders_InternalWONumber`, `IX_workOrders_SiteCode` (P2, após fix tamanho coluna)
|
|
|
|
### 6. WorkOrderType
|
|
|
|
- Mapear coluna legada `WorkOrderType varchar(50)` na entidade EF
|
|
- Expor em `WorkOrderBoardRowDto`
|
|
- `IsPastDue` em presentation — **não** confundir com tipo
|
|
- Enum C# adiado até amostragem prod
|
|
|
|
### 7. Status mapping
|
|
|
|
- API retorna status **canônico** (`Open`, `InProgress`, `Completed`, `Cancelled`, `OnHold`)
|
|
- `StatusDisplay` via `IWorkOrderStatusMapper` (workshop G2 separado)
|
|
- Sem migration de enum DB
|
|
|
|
---
|
|
|
|
## Consequências
|
|
|
|
### Positivas
|
|
|
|
- 1 HTTP call por mudança de semana (FE)
|
|
- Contrato estável para board sem acoplar CRUD legado
|
|
- Performance previsível (janela + threshold 300)
|
|
- Blazor legado inalterado (EF local)
|
|
|
|
### Negativas / trade-offs
|
|
|
|
- Duplicação parcial de lógica de listagem vs `GetWorkOrderList` (aceitável — bounded contexts distintos)
|
|
- Vendor technician pode ser null Fase 1 se dispatch spike incompleto
|
|
- Setup DB local necessário para validação integrada
|
|
|
|
---
|
|
|
|
## Compliance com spikes
|
|
|
|
| Spike | Gate | Resultado |
|
|
|-------|------|-----------|
|
|
| Consumer Audit | G0 | `GetWorkOrderList` órfão no repo — endpoint dedicado aprovado |
|
|
| WorkOrderType | G1 | Mapear coluna EF; Overdue = presentation |
|
|
| Search Strategy | G3 | Window-first, threshold 300, StartsWith identificadores |
|
|
|
|
---
|
|
|
|
## Fora de escopo Fase 1
|
|
|
|
- PATCH inline edit
|
|
- Completion doc, media, flags, reorder
|
|
- Search vendor/tech server-side
|
|
- Paginação cross-week
|
|
- Alteração de `GetWorkOrderList`
|
|
|
|
---
|
|
|
|
## Próximos passos (implementação)
|
|
|
|
1. Aprovação explícita **Fase 1 only**
|
|
2. Migration: `WorkOrderType` + índice `ScheduledDate`
|
|
3. `GetWorkOrdersBoard` em `WorkOrderController` + `WorkOrderDataService`
|
|
4. DTOs + `IWorkOrderBoardMapper`
|
|
5. FE: `useWorkOrdersBoard({ from, to })` substituindo `RAW_ORDERS`
|
|
|
|
---
|
|
|
|
## Referências
|
|
|
|
- Gap analysis v3: `work_orders_api_gap_analysis_ce735946.plan.md`
|
|
- [`WorkOrderController.cs`](../../Api.SeaHavenIndustries/Controllers/WorkOrderController.cs)
|
|
- [`WorkOrderDataService.cs`](../../SeaHaven.DataServices/Implementation/WorkOrderDataService.cs)
|
|
- [`DispatchController.List`](../../Api.SeaHavenIndustries/Controllers/DispatchController.cs) — padrão janela temporal
|