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

163 lines
5.5 KiB
Markdown
Raw Normal View History

# Fase 4 — Search contextual + Advanced Search
**Programa:** Work Orders Board
**Objetivo:** Hardening da busca contextual no board semanal, endpoint de advanced search cross-week (Tier S), índices de suporte e harness de load test.
**Depende de:** [Fase 0](../phase-0/README.md), [Fase 1](../phase-1/README.md), [Fase 2](../phase-2/README.md), [Fase 3](../phase-3/README.md)
**Tier vigente (dev):** **S (provisório)** — ver [search-tier-decision.md](./search-tier-decision.md)
---
## Endpoints
### `GET /api/workorders/board?search=` (hardening)
Busca contextual na janela semanal. Campos cobertos:
| Campo | Origem |
|-------|--------|
| Site | `SiteCode` |
| WO# | `InternalWONumber`, `WorkerOrderNumber` |
| Location | `Locations.Name` |
| Dispatcher | `AssignToUser` nome |
| PM | `Trade`, `Problem` |
| Vendor | `PrimaryDispatch.Vendor.CompanyName` |
| Tech | `PrimaryDispatch.Vendor.ContactName` |
| Status legado | `Status` |
| Lifecycle | label enum (`Scheduled`, `In Progress`, etc.) |
**Regras:**
- `search` com trim; ignorado se vazio ou < 2 caracteres
- `counts.total` — agendadas na semana **sem** search
- `counts.returned` — agendadas **com** search
### `GET /api/workorders/board/search`
Advanced search cross-week paginado.
**Autenticação:** Bearer JWT
**Query params:**
| Param | Tipo | Descrição |
|-------|------|-----------|
| `search` | string | Texto livre (mesmos campos do contextual) |
| `datePreset` | enum | `thisWeek`, `lastWeek`, `thisMonth`, `last3Months`, `nextWeek`, `nextMonth`, `custom` |
| `dateFrom` / `dateTo` | date | Obrigatórios se `datePreset=custom` |
| `sites` | string[] | `SiteCode` |
| `types` | WorkOrderType[] | Tipo WO |
| `dispatchers` | string[] | GUIDs + `__unassigned__` |
| `statuses` | LifecycleStatus[] | Status operacional |
| `pmTypes` | string[] | Match em `Trade`/`Problem` (contains, case-insensitive) |
| `vendorIds` | int[] | Via `PrimaryDispatch.VendorId` |
| `docStatuses` | DocStatus[] | Enum `DocStatus` |
| `myWorkOrders` | bool | Filtro usuário logado |
| `page` | int | Default 1 |
| `pageSize` | int | Default 50; max 100 (Tier S/M) |
| `sortBy` | string | `scheduledDate` (default), `woNumber`, `dueDate` |
| `sortDir` | string | `asc` / `desc` |
**Response:** `PagedResult<WorkOrderBoardRowDto>`
```json
{
"items": [ /* WorkOrderBoardRowDto */ ],
"totalCount": 120,
"page": 1,
"pageSize": 50,
"totalPages": 3,
"hasNext": true,
"hasPrevious": false
}
```
**Exemplo:**
```bash
curl -H "Authorization: Bearer <token>" \
"https://localhost:5001/api/workorders/board/search?datePreset=thisMonth&sites=BK5&search=HVAC&page=1"
```
---
## Matriz preset → intervalo de datas
Base: **segunda-feira ISO** (`WorkOrderSearchDateRangeResolver`).
| Preset | Intervalo |
|--------|-----------|
| `thisWeek` | Seg–Dom da semana ISO corrente |
| `lastWeek` | Seg–Dom da semana ISO anterior |
| `nextWeek` | Seg–Dom da próxima semana ISO |
| `thisMonth` | 1º–último dia do mês corrente |
| `nextMonth` | 1º–último dia do mês seguinte |
| `last3Months` | Hoje − 3 meses → hoje |
| `custom` | `dateFrom` / `dateTo` (400 se ausentes) |
**Filtro de data:** `ScheduledDate` no intervalo **OU** `ScheduleWeekOnly && TargetWeek` intersectando o intervalo. Exclui templates e `IsDeleted`.
---
## Código entregue
| Camada | Arquivo |
|--------|---------|
| Search filter | `SeaHaven.DataServices/Helpers/WorkOrderBoardSearchFilter.cs` |
| Query filters | `SeaHaven.DataServices/Helpers/WorkOrderBoardQueryFilters.cs` |
| Projeção | `SeaHaven.DataServices/Helpers/WorkOrderBoardProjection.cs` |
| Date presets | `SeaHaven.Services/Helpers/WorkOrderSearchDateRangeResolver.cs` |
| Advanced data | `SeaHaven.DataServices/Implementation/WorkOrderAdvancedSearchDataService.cs` |
| Advanced service | `SeaHaven.Services/Implementation/WorkOrderAdvancedSearchService.cs` |
| DTOs | `SeaHaven.Services/DTOs/WorkOrderBoardDTOs.cs` |
| API | `WorkOrderController` — `GET board/search` |
| Migration | `20260624200000_Phase4_SearchIndexes.cs` |
| Testes | `SeaHavenIndustries.Tests/WorkOrderBoardSearchTests.cs` |
| Load test | `scripts/load-test/work-order-search.k6.js` |
| Seed | `scripts/seed-work-orders-search.ps1` |
---
## Gates de aceite
### Dev (implementação)
- [x] Helper de search compartilhado + testes por campo
- [x] `GET /board/search` paginado com filtros FE
- [x] Date presets alinhados ao SHOC (ISO Monday)
- [x] Migration índices Phase 4
- [x] Harness k6 + seed sintético (Tier S local)
- [x] Endpoints legados inalterados
- [x] ~12 testes unitários novos (total ~80)
### Staging/prod (GO — pendente)
- [ ] Volume Discovery preenchido — [volume-discovery-report.md](../phase-0/volume-discovery-report.md)
- [ ] Tier assinado — [search-tier-decision.md](./search-tier-decision.md)
- [ ] Load test em staging com volume real
- [ ] Latência dentro do SLO do tier confirmado
- [ ] Smoke Portal/Blazor inalterados
---
## SLOs Tier S (load test local)
| Cenário | Endpoint | p95 |
|---------|----------|-----|
| Board sem search | `GET /board?weekStart=...` | &lt; 800ms |
| Board com search | `GET /board?search=BK5` | &lt; 1000ms |
| Advanced preset | `GET /board/search?datePreset=thisMonth` | &lt; 1200ms |
| Advanced multi-filter | sites + types + search | &lt; 1500ms |
Ver [scripts/load-test/README.md](../../scripts/load-test/README.md).
---
## Fora de escopo
- Full-text search (Tier L)
- Search externo dedicado (Tier XL)
- Lookups PM catalog (`PM_TYPES`) — backlog #17
- Alterações em endpoints legados