mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-01 02:53:14 +00:00
163 lines
5.5 KiB
Markdown
163 lines
5.5 KiB
Markdown
|
|
# 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=...` | < 800ms |
|
|||
|
|
| Board com search | `GET /board?search=BK5` | < 1000ms |
|
|||
|
|
| Advanced preset | `GET /board/search?datePreset=thisMonth` | < 1200ms |
|
|||
|
|
| Advanced multi-filter | sites + types + search | < 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
|