mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-01 06:23:16 +00:00
87 lines
2.1 KiB
Markdown
87 lines
2.1 KiB
Markdown
# ManualEditFlag — Design
|
|
|
|
**Fase:** 0
|
|
**Implementação:** tabela satélite `WorkOrderFieldLocks`
|
|
|
|
---
|
|
|
|
## 1. Problema
|
|
|
|
Sync/Lambda faz upsert overwrite em campos que dispatchers editam no SHOC. Precisamos saber, por campo, se houve edição manual SHOC para rejeitar ingest conflitante.
|
|
|
|
---
|
|
|
|
## 2. Solução escolhida: tabela satélite
|
|
|
|
```text
|
|
WorkOrderFieldLocks
|
|
Id (PK)
|
|
WorkOrderId (FK)
|
|
FieldName (string, max 64)
|
|
LockedAt (UTC)
|
|
LockedByUserId (nullable — null = system/bootstrap)
|
|
UNIQUE (WorkOrderId, FieldName)
|
|
```
|
|
|
|
**Alternativa descartada:** bitmask — difícil de auditar e estender.
|
|
|
|
---
|
|
|
|
## 3. Comportamento
|
|
|
|
| Evento | Ação |
|
|
|--------|------|
|
|
| SHOC edita campo X pela 1ª vez | INSERT lock (WorkOrderId, FieldName) |
|
|
| Sync tenta atualizar campo X com lock | Skip update; audit `SyncRejected` |
|
|
| Sync atualiza campo Y sem lock | Apply merge normal |
|
|
| WO novo (Sync create) | Sem locks; full ingest |
|
|
| Blazor edita campo legado | **Não** cria lock Fase 0 (gap conhecido; Blazor congelado) |
|
|
|
|
---
|
|
|
|
## 4. Campos elegíveis a lock (SHOC writers)
|
|
|
|
Definidos em `SyncFieldMergePolicy.ShocOwnedFields`:
|
|
|
|
- LifecycleStatus, AssignTo, ScheduledDate, ScheduledEnd, TargetWeek, ScheduleWeekOnly
|
|
- DueDate, Description, WorkerOrderTitle, SiteCode, Building, LocationId
|
|
- WorkOrderType, DocStatus, Trade, Problem, Priority, InternalWONumber
|
|
|
|
---
|
|
|
|
## 5. Audit em rejeição
|
|
|
|
```json
|
|
{
|
|
"eventType": "Sync",
|
|
"action": "SyncRejected",
|
|
"fieldName": "DueDate",
|
|
"oldValue": "2026-06-01",
|
|
"newValue": "2026-06-15",
|
|
"actorType": "Sync"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. API interna
|
|
|
|
```csharp
|
|
interface IWorkOrderFieldLockService
|
|
{
|
|
Task LockFieldAsync(int workOrderId, string fieldName, string? userId);
|
|
Task<bool> IsLockedAsync(int workOrderId, string fieldName);
|
|
}
|
|
```
|
|
|
|
Implementação: `WorkOrderFieldLockService` em `SeaHaven.Services`.
|
|
|
|
Lock criado automaticamente por `IWorkOrderAuditService` em eventos `Manual` + `FieldChanged` / `StatusChanged`.
|
|
|
|
---
|
|
|
|
## 7. Critérios de aceite
|
|
|
|
- [ ] Tabela criada na migration Phase0
|
|
- [ ] Sync consulta locks antes de overwrite
|
|
- [ ] SyncRejected aparece no audit log
|