# F) SOURCE OF TRUTH — quem manda em cada dado

> Regra: **um dado tem um dono só.** Quem não é dono lê, cacheia e emite evento — nunca reescreve.
> "Hoje" = enquanto a Nuvemshop estiver no ar. "Depois" = após o cutover (Onda 15).

| Dado | Dono HOJE | Dono DEPOIS | Consumidores | Sincronização |
|---|---|---|---|---|
| **Produto / variante / SKU** | Nuvemshop | **Medusa** | Agente IA (`catalogo_indice`), catálogo PDF, marketing-criativos, painel-lucro, venda-manual | Hoje: NS → Medusa (import 1 via, idempotente por `external_id`). Depois: Medusa → fachada NS-compatível |
| **Preço / preço promocional** | Nuvemshop | **Medusa** | precificação, painel-lucro, banners | `vo/config/precificacao.php` escreve na NS hoje; depois escreve na Commerce API |
| **Custo do produto** | Nuvemshop (campo `cost`) | **Medusa** (metadata) | `painel_lucro_sku`, cálculo de lucro | Lido na sincronização de pedido pendente |
| **Montagem por SKU** | **MySQL `painel_lucro_sku`** | igual | dar-baixa (trava a baixa), OS | Nenhuma — já é local |
| **Estoque** | Nuvemshop | **Medusa** | vitrine de anúncios, storefront | ⚠️ `stock NULL` na NS = estoque **infinito** (lição de 24/07) |
| **Categoria / marca** | Nuvemshop | **Medusa** | storefront, chips de categoria do marketing | Import 1 via |
| **Carrinho / checkout** | Nuvemshop | **Medusa** | `cron-carrinho-abandonado` | Hoje `GET /checkouts`; depois eventos próprios |
| **Pedido (comercial)** | Nuvemshop | **Medusa** | ERP inteiro | Espelho em `pedidos_cache` (chave `nuvemshop_id`, novo: `LP-000123`) |
| **Pedido (operacional: baixa, lucro, custo real, taxa)** | **MySQL `pedidos_cache`** | igual | PDV, relatórios, painel de lucro | Nunca volta pra loja |
| **Pagamento confirmado** | **Humano no PDV** (`dar-baixa.php`) | igual (até decisão contrária) | comissão, cashback, CAPI, CRM | — |
| **Comissão MMN** | **MySQL `comissoes`** | igual | painel afiliado, saques, metas | **A loja nova nunca calcula comissão** |
| **Saque** | **MySQL `saques`** | igual | painel afiliado, admin | — |
| **Meta mensal do afiliado** | **MySQL `afiliado_metas`** | igual | notificação de venda | Recalculada a cada baixa |
| **Afiliado / árvore MMN** | **MySQL `afiliados`** | igual | atribuição, painel, catálogo | Loja nova só **lê** (`GO_n` → `afiliado_id`) |
| **Atribuição da venda** | Nuvemshop (`customer_visit.utm_parameters`) | **Commerce API** (cookie 1st-party + carrinho) | `sincronizar.php` → `pedidos_cache.afiliado_id` | Passa a ser **mais confiável** que hoje |
| **Identidade do cliente** | **MySQL `clientes`** (`vo/config/clientes.php`) | igual | painel do cliente, cashback, CRM | Cascata CPF → telefone(DDD+8) → `ns_customer_id` → e-mail. Loja nova chama esse mesmo motor |
| **Conta/senha do cliente** | **MySQL `clientes.senha_hash`** | igual | `cliente.ofertadistribuidora.com.br` | Login por CPF+senha; recuperação só por e-mail (motivo: 49 pedidos têm telefone do afiliado) |
| **Cashback (ledger)** | **MySQL `cashback_mov`** | igual | painel do cliente, checkout novo | **Saldo é sempre soma de movimentações.** Nunca criar campo `saldo` |
| **Cupom de cashback** | Nuvemshop (`/coupons`) | **Medusa** | resgate, `cron-cashback` | Gerar ≠ gastar: vira `reserva`, só vira `uso` quando o pedido entra |
| **Cupom de afiliado** | Nuvemshop | **Medusa** | `afiliado/api/criar-cupom.php` | — |
| **Lead / CRM / funil / score** | **MySQL** (`leads`, `chat_conversas`, `crm_*`) | igual | CRM afiliado + admin | Loja nova só **emite evento** |
| **Conversa de WhatsApp** | **MySQL** (`chat_*`) + Evolution | igual | chat, agente IA | Intocado |
| **Gasto de anúncio / insights** | Meta Graph API → `meta_insights_dia` | igual | Marketing OS | Cron diário |
| **Público (Custom Audience)** | Meta | igual | `cron-sincronizar-publicos` | `usersreplace`, PHONE_SHA256 |
| **Evento Purchase (CAPI)** | **`dar-baixa.php`** | igual | Meta | `event_id = pedido-{id}` — **um emissor só, nunca dois** |
| **Ordem de serviço / montador** | **MySQL `ordens_servico`, `montadores`** | igual | painel do montador, aprovação de pagamento | Pedido novo alimenta; nada muda de lugar |
| **Foto da montagem** | Disco `vo/fotos_os` | igual | aprovação de pagamento do montador | ⚠️ Continua gravando na pasta do `vo` (decisão de 25/07) |
| **Conteúdo da loja (banner, vitrine, SEO)** | Tema da Nuvemshop | **Medusa (módulo CMS nosso)** | storefront | Recriado, não migrado |

---

## Como cada evento novo se conecta ao que já existe

| Evento da loja nova | Vai para | Efeito |
|---|---|---|
| `product_viewed` | CRM (`interesses`) + Pixel `ViewContent` | ⚠️ Isso **não existia** — o CRM-PLANO cortou "produtos visualizados" por falta do dado. A loja nova **destrava** esse recurso |
| `cart_created` / `cart_updated` | Commerce API (`carts`) | Base do abandono |
| `checkout_started` | Pixel `InitiateCheckout` + CRM | — |
| `checkout_abandoned` | `carrinhos_abandonados` (tabela que já existe) | Reaproveita as **5 travas** do cron atual |
| `order_created` | `vo/api/loja-pedido.php` → `pedidos_cache` | Notifica afiliado + admin (push/WhatsApp), igual hoje |
| `order_paid` | (por ora, humano no PDV) | Comissão + cashback + CAPI + CRM |
| `order_cancelled` | `vo/api/estornar-pedido.php` | Comissão `cancelada` + `cbEstornarPedido` |
| `coupon_used` | `cbConfirmarUso()` | Reserva → consumo |

---

## Proibições explícitas

- ❌ criar `clientes2`, `pedidos2`, `comissoes2`, `cashback2`, `crm2`;
- ❌ criar campo `saldo_cashback` em qualquer lugar;
- ❌ calcular comissão fora do `dar-baixa.php`;
- ❌ escrever na Nuvemshop a partir da loja nova;
- ❌ renomear/apagar coluna existente do `ofertadi_os`;
- ❌ mandar dois `Purchase` para a Meta pelo mesmo pedido.
