shoc-backend/docs/work-orders/phase-7/lambda-ingest-discovery.md

94 lines
3.3 KiB
Markdown
Raw Normal View History

# Lambda Ingest — Descoberta e Mapeamento de Campos
**Fase:** 7
**Status:** Documentação de cutover (código Lambda fora deste repositório)
---
## 1. Localização da Lambda
| Item | Valor |
|------|-------|
| Nome referenciado | `workorder-ingest` |
| Referência código | [TODO.md](../../../TODO.md) L50–51 |
| Fluxo atual | Lambda → DynamoDB (`WorkOrders`) → `POST api/Sync/WorkOrders` |
| Fluxo alvo | Lambda → `POST api/workorders/ingest` (API key) |
**Ação pendente ops:** localizar repositório/infra AWS (SAM, Terraform, console Lambda) e preencher owner na [phase-7-gates-signoff.md](phase-7-gates-signoff.md).
---
## 2. Tabelas DynamoDB (SyncController)
| Tabela | Endpoint sync | Uso |
|--------|---------------|-----|
| `WorkOrders` | `POST api/Sync/WorkOrders` | Upsert WO por `work_order_id` |
| `WorkOrderComments` | `POST api/Sync/Comments` | Comentários cliente |
| `VendorReplies` | `POST api/Sync/VendorReplies` | Respostas vendor |
Cutover Fase 7 foca em **WorkOrders**; comments/replies permanecem no Sync até migração separada.
---
## 3. Mapeamento DynamoDB → API ingest
Campos lidos em [SyncController.cs](../../../Api.SeaHavenIndustries/Controllers/SyncController.cs) e espelhados em `WorkOrderIngestPayload`:
| Campo Dynamo | Campo API ingest | Campo SQL | Merge policy (update) |
|--------------|------------------|-----------|------------------------|
| `work_order_id` | `externalWorkOrderId` | `ExternalWorkOrderId` | Chave idempotente |
| `description` | `description` | `Description`, `WorkerOrderTitle` | Sim se não locked |
| `wo_status` | `woStatus` | `Status` (mapeado) | Sim se não locked |
| `severity` | `severity` | `Priority`, `Severity` | Sim se não locked |
| `customer` | `customer` | `Customer` | Direto na criação |
| `site_code` | `siteCode` | `SiteCode` | Sim se não locked |
| `building` | `building` | `Building` | Sim se não locked |
| `address` | `address` | `Locations` (resolve/create) | LocationId |
| `due_date` | `dueDate` | `DueDate` | Sim se não locked |
| `date_reported` | `dateReported` | `DateReported` | Direto |
| `scheduled_start` | `scheduledStart` | `ScheduledStart` | Direto |
| `source_email_s3_key` | `sourceEmailS3Key` | `SourceEmailS3Key` | Direto |
| `created_at` | `createdAt` | `CreatedDate` | Criação only |
### Mapeamento `wo_status` → SQL `Status`
| Dynamo | SQL |
|--------|-----|
| `new`, `assigned`, `unknown` | `Open` |
| `in_progress` | `In Progress` |
| `on_hold` | `On Hold` |
| `completed` | `Done` |
| `cancelled` | `Cancelled` |
### Mapeamento `severity` → `Priority`
`Sev {severity}` (ex.: `3` → `Sev 3`)
---
## 4. Auth serviço-a-serviço
| Header | Config |
|--------|--------|
| `X-Ingest-Key` | `WorkOrderIngest:ApiKey` (env `WorkOrderIngest__ApiKey`) |
Lambda deve enviar o header em cada `POST /api/workorders/ingest`. Não usar JWT de usuário dispatcher.
---
## 5. Estratégia dual-run
1. **Semana 1–2:** Lambda grava DynamoDB **e** chama API ingest
2. **Validação:** `GET /api/workorders/ops/health` + script amostra `ExternalWorkOrderId`
3. **Cutover:** Lambda só API; `Sync:Enabled=false`
4. **Retire:** backup DynamoDB → desativar tabelas
---
## 6. Critérios de cutover
- [ ] `POST /api/workorders/board` estável (criação SHOC)
- [ ] Auth ingest testada em staging
- [ ] Zero drift em amostra de 100 WOs
- [ ] Owner Lambda assinou runbook