mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 18:53:12 +00:00
119 lines
4 KiB
Markdown
119 lines
4 KiB
Markdown
# Fase 5 — Scheduled Domain Events
|
|
|
|
**Programa:** Work Orders Board
|
|
**Objetivo:** Jobs agendados in-process (`IHostedService`) para `WeekRolled` → `CarriedOver++` com idempotência WO+semana, audit System, cache opcional de `PastDue`, e garantia de que leituras do board continuam on-read como fonte da verdade.
|
|
|
|
**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), [Fase 4](../phase-4/README.md)
|
|
|
|
---
|
|
|
|
## Regra de elegibilidade WeekRolled
|
|
|
|
```text
|
|
sourceWeek = semana operacional encerrada (segunda a sexta UTC)
|
|
Elegível se:
|
|
- ScheduledDate.Date ∈ [sourceWeekStart, sourceWeekEnd]
|
|
- LifecycleStatus ∉ {Complete, Canceled, Closed}
|
|
- istemplate != true (ou null)
|
|
- Ainda não processado em WorkOrderWeekRolledLedger (WorkOrderId + SourceWeekStart)
|
|
```
|
|
|
|
**Gate PO (pendente):** confirmar se WOs só com `TargetWeek` (sem `ScheduledDate`) entram no carry-over. A implementação atual considera **apenas** WOs com `ScheduledDate` na janela.
|
|
|
|
---
|
|
|
|
## Idempotência
|
|
|
|
Chave composta `(WorkOrderId, SourceWeekStart)` na tabela `WorkOrderWeekRolledLedger`. Re-execução do job ou endpoint admin na mesma semana não duplica `CarriedOver`.
|
|
|
|
---
|
|
|
|
## Contrato de audit
|
|
|
|
Um evento `WeekRolled` por WO processado:
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| `EventType` | `System` |
|
|
| `ActorType` | `System` |
|
|
| `Action` | `WeekRolled` |
|
|
| `FieldName` | `CarriedOver` |
|
|
| `OldValue` / `NewValue` | numéricos (string) |
|
|
| `CorrelationId` | `week:{yyyy-MM-dd}` (segunda da semana fonte) |
|
|
|
|
Não aciona `ManualEditFlag` nem field locks.
|
|
|
|
---
|
|
|
|
## Regra de ouro — isPastDue
|
|
|
|
Jobs **nunca** são fonte da verdade para `isPastDue`. O board continua calculando via `WorkOrderDerivedFields.IsPastDue` on-read. O cache `OperationalFlags.PastDue` é otimização opcional (`WorkOrderJobs:PastDueCache:Enabled`, default **false**).
|
|
|
|
---
|
|
|
|
## Configuração
|
|
|
|
```json
|
|
"WorkOrderJobs": {
|
|
"WeekRolled": { "Enabled": true, "RunAtUtc": "00:05", "DayOfWeek": "Monday" },
|
|
"PastDueCache": { "Enabled": false, "RunAtUtc": "00:10" }
|
|
}
|
|
```
|
|
|
|
Variáveis de ambiente (`.env.example`):
|
|
|
|
```text
|
|
WorkOrderJobs__WeekRolled__Enabled=true
|
|
WorkOrderJobs__PastDueCache__Enabled=false
|
|
```
|
|
|
|
---
|
|
|
|
## Endpoints admin (ops-only)
|
|
|
|
| Endpoint | Auth | Descrição |
|
|
|----------|------|-----------|
|
|
| `POST /api/workorders/jobs/week-rolled?sourceWeekStart=2026-06-16` | Admin | Reprocessa semana (segunda-feira). Idempotente. |
|
|
| `POST /api/workorders/jobs/past-due-cache` | Admin | Atualiza cache `OperationalFlags.PastDue` |
|
|
|
|
---
|
|
|
|
## Código entregue
|
|
|
|
| Camada | Arquivo |
|
|
|--------|---------|
|
|
| Ledger | `Data.SeaHavenIndustries/Models/WorkOrderWeekRolledLedger.cs` |
|
|
| Migration | `20260624210000_Phase5_DomainEvents.cs` |
|
|
| Data | `SeaHaven.DataServices/Implementation/WorkOrderDomainJobDataService.cs` |
|
|
| WeekRolled | `SeaHaven.Services/Implementation/WorkOrderWeekRolledService.cs` |
|
|
| PastDue cache | `SeaHaven.Services/Implementation/PastDueCacheService.cs` |
|
|
| Hosted | `Api.SeaHavenIndustries/HostedServices/*.cs` |
|
|
| API | `WorkOrderJobsController` |
|
|
| Testes | `SeaHavenIndustries.Tests/WorkOrderWeekRolledTests.cs` |
|
|
|
|
---
|
|
|
|
## Monitoramento
|
|
|
|
Logs estruturados com `CorrelationId` da semana. Ao concluir: `processed`, `skipped`, `failed`, `durationMs`.
|
|
|
|
**Alerta ops:** se `failed > 0` ou job não executou em 8 dias → investigar + `POST /jobs/week-rolled` manual.
|
|
|
|
---
|
|
|
|
## Critérios de aceite
|
|
|
|
- [x] Job semanal incrementa `carriedOver` para WOs elegíveis da semana anterior
|
|
- [x] Re-execução na mesma semana não duplica (ledger WO+semana)
|
|
- [x] Audit `WeekRolled` System com old/new `CarriedOver` e `CorrelationId`
|
|
- [x] `GET /api/workorders/board` continua com `isPastDue` derivado on-read
|
|
- [x] Endpoint admin permite reprocessar semana específica
|
|
- [x] Testes cobrem idempotência, terminal skip, audit e on-read correctness
|
|
|
|
---
|
|
|
|
## Fora de escopo
|
|
|
|
- Message queue / worker externo
|
|
- Alteração do contrato REST do board para usar `OperationalFlags`
|
|
- WOs week-only (`TargetWeek` sem `ScheduledDate`) — gate PO
|