# 04 - SERVICES E STATE MACHINES

## 1. ARQUITETURA DOS SERVICES

Os Services sao **compartilhados** entre Marketplace Web e API REST. Ficam em um unico local e sao referenciados por ambos.

```
Services/
|-- Shared/
|   |-- StateMachine.php          # Motor generico
|   |-- EventDispatcher.php       # Singleton: event_store + Redis
|   |-- IdempotencyGuard.php      # Lock via MySQL
|   |-- OrderStateMachine.php     # Transicoes do pedido
|-- OrderService.php
|-- PaymentService.php
|-- StockService.php
|-- LedgerService.php
|-- SettlementService.php
|-- FiscalService.php
|-- ReturnService.php
|-- AdsService.php
|-- TmsService.php
|-- CdSyncService.php
|-- RulesEngineService.php
|-- Gateways/
|   |-- GatewayInterface.php
|   |-- MercadoPagoGateway.php
|   |-- GetnetGateway.php
```

### Padroes Recorrentes
- **Lock pessimista:** `SELECT ... FOR UPDATE` em todas operacoes de estoque/financeiro
- **Idempotencia:** `IdempotencyGuard.acquire(key)` antes de operacoes criticas
- **Event Sourcing:** `EventDispatcher.dispatch()` persiste no `event_store` + publica Redis
- **Double-Entry:** `LedgerService.record()` debita + credita atomicamente
- **Transacao atomica:** `beginTransaction() / commit() / rollback()`

---

## 2. STATE MACHINES (10)

### 2.1 ORDER (Pedido Master)
```
Estados: pending, confirmed, processing, partially_shipped, shipped,
         partially_delivered, delivered, completed, disputed, refunded, cancelled

Transicoes:
  pending -> confirmed          # Pagamento autorizado
  pending -> cancelled          # Timeout ou cliente cancelou
  confirmed -> processing       # Splits criados + estoque reservado
  confirmed -> cancelled        # Admin cancelou
  processing -> partially_shipped
  processing -> shipped
  processing -> cancelled       # Admin cancelou (com estorno)
  partially_shipped -> shipped
  partially_shipped -> partially_delivered
  shipped -> partially_delivered
  shipped -> delivered
  partially_delivered -> delivered
  delivered -> completed        # Prazo disputa expirou (D+14)
  delivered -> disputed         # Cliente abriu disputa
  disputed -> refunded          # Favor comprador
  disputed -> completed         # Favor vendedor

Timeouts:
  PIX: 30 minutos
  Boleto: 24 horas
```

### 2.2 ORDER SPLIT (Sub-pedido por Seller)
```
Estados: pending, processing, picking, packed, short, shipped,
         in_transit, out_for_delivery, delivered, failed_delivery,
         returning, returned, cancelled

Transicoes:
  pending -> processing -> picking -> packed -> shipped ->
  in_transit -> out_for_delivery -> delivered
  
  out_for_delivery -> failed_delivery (ate 3 tentativas)
  failed_delivery -> out_for_delivery (nova tentativa)
  failed_delivery -> returning (apos 3a falha)
  returning -> returned
  picking -> short (item nao encontrado)
```

### 2.3 PAYMENT TRANSACTION
```
Estados: pending, authorized, captured, paid, partially_refunded,
         refunded, chargeback, in_dispute, failed, expired, cancelled

Por metodo:
  PIX:    pending -> paid
  Boleto: pending -> paid | pending -> expired
  Credito: pending -> authorized -> captured -> paid
  Debito: pending -> authorized -> paid
  Wallet: pending -> paid

Chargeback: debito na wallet do seller
```

### 2.4 PAYMENT SPLIT (Repasse)
```
Estados: pending, scheduled, processing, settled, failed, manual_review, reversed

  pending -> scheduled      # Pedido entregue + D+14
  scheduled -> processing   # Job settlement
  processing -> settled     # Transferencia OK
  processing -> failed      # Ate 3 retries, depois manual_review
```

### 2.5 SHIPMENT
```
Estados: pending, label_created, picked_up, in_transit, out_for_delivery,
         delivered, failed_delivery, returning, returned, lost, cancelled

  lost -> sinistro transportadora + estorno automatico
```

### 2.6 FISCAL DOCUMENT (NF-e)
```
Estados: draft, validating, signed, authorized, rejected, contingency, cancelled, cc_e

  draft -> validating -> signed -> authorized (cStat 100)
  signed -> rejected (SEFAZ rejeitou)
  signed -> contingency (SEFAZ indisponivel: EPEC, SVC-AN, SVC-RS)
  authorized -> cancelled (ate 24h NF-e, 30min NFC-e)
  authorized -> cc_e (max 20 por doc)
```

### 2.7 RETURN / RMA
```
Estados: requested, approved, rejected, shipped_back, received,
         inspected, refunded, partial_refund, closed, expired

  CDC: 7 dias para arrependimento
  Expira: 15 dias se cliente nao posta
  Restock: se condition = new/used
```

### 2.8 PICKING ORDER
```
Estados: pending, assigned, in_progress, completed, short, cancelled
  Variancia > 5% -> exige aprovacao supervisor
```

### 2.9 INVENTORY COUNT
```
Estados: planned, in_progress, pending_approval, approved
  Gera stock_movements tipo 'count'/'adjustment'
```

### 2.10 ADS CAMPAIGN
```
Estados: draft, active, paused, exhausted, completed, cancelled
  spent_today >= daily_budget -> exhausted
  Reset diario meia-noite reativa
```

---

## 3. SERVICES - METODOS PUBLICOS

### 3.1 OrderService
| Metodo | Descricao |
|--------|-----------|
| `createFromCheckout(params)` | Cria pedido do carrinho: valida estoque, calcula totais, gera UPP-YYYYMMDD-XXXXX, itens com comissao, marca carrinho convertido. Dispara `order.created` |
| `changeStatus(orderId, newStatus, changedBy, reason)` | Lock pessimista, valida state machine, atualiza timestamps especificos, historico. Dispara `order.{status}` |
| `createSplits(orderId)` | Agrupa itens por seller, calcula commission + seller_net, roteia warehouse. Dispara `order.splits_created` |

### 3.2 PaymentService
| Metodo | Descricao |
|--------|-----------|
| `processPayment(orderId, gateway, payments[])` | Multi-payment (PIX+cartao), cria transactions, payment_splits. Dispara `payment.{status}` |
| `handleWebhook(gateway, eventType, payload)` | Persiste webhook, localiza transacao, mapeia status, atualiza pedido |
| `refund(transactionId, amount, reason)` | Estorno total/parcial, reverte splits pendentes. Dispara `payment.refunded` |

### 3.3 StockService
| Metodo | Descricao |
|--------|-----------|
| `getAvailable(productId, variantId, warehouseId)` | Soma available de wms_stock |
| `reserve(productId, variantId, qty, warehouseId, ...)` | Lock + incrementa reserved + movimento 'reserve'. Dispara `stock.reserved` |
| `release(productId, variantId, qty, warehouseId, ...)` | Libera reserva, GREATEST(0) para evitar negativo |
| `deduct(productId, variantId, qty, warehouseId, ...)` | Baixa definitiva: qty - qty, reserved - qty. Dispara `stock.low` se <= min |
| `inbound(productId, variantId, sellerId, qty, ...)` | Entrada: cria ou incrementa wms_stock |

### 3.4 LedgerService (Double-Entry)
| Metodo | Descricao |
|--------|-----------|
| `record(type, debitAccId, creditAccId, amount, desc)` | Lock nas 2 contas, cria transaction + 2 entries. Soma global sempre zero |
| `recordSale(orderId, sellerId, saleAmount, commission)` | 2 lancamentos: escrow->receivable (total) + receivable->commission (comissao) |

### 3.5 SettlementService
| Metodo | Descricao |
|--------|-----------|
| `generateSettlement(sellerId, start, end, safetyDays=14)` | Busca splits pendentes de pedidos entregues ha +14d, calcula gross/net, cria settlement |
| `executeTransfer(settlementId)` | Transferencia real (PIX/TED), atualiza splits para 'settled' |

### 3.6 FiscalService
| Metodo | Descricao |
|--------|-----------|
| `emitNFe(orderSplitId)` | Draft: CFOP 5102/6102, impostos por regime (Simples: CSOSN 102, Presumido: ICMS 18%, PIS 0.65%, COFINS 3%) |
| `signAndSubmit(documentId)` | Assina XML (NFePHP) + envia SEFAZ. cStat 100 = authorized |
| `cancel(documentId, justification)` | Prazo: 24h NF-e, 30min NFC-e. Justificativa 15-255 chars |
| `emitCCe(documentId, correction)` | Max 20 por doc, 15-1000 chars |

### 3.7 ReturnService
| Metodo | Descricao |
|--------|-----------|
| `request(orderId, userId, reason, items, desc)` | Valida: delivered/completed, CDC 7 dias. Calcula estorno |
| `approve(returnId, approvedBy)` | Gera codigo logistica reversa |
| `receiveAndInspect(returnId, itemConditions[])` | Inspeciona, restock se new/used, finaliza como refunded |

### 3.8 AdsService
| Metodo | Descricao |
|--------|-----------|
| `recordImpression(campaignId, ...)` | Frequency cap, custo CPM, verifica exaustao budget |
| `recordClick(impressionId, ...)` | Anti-fraude: 3+ clicks/IP/60s = fraud_score 0.95 |
| `recordConversion(clickId, orderId, value)` | Attribution last_click |
| `getAdsForPlacement(placement, categoryId, limit)` | Leilao second-price: rank = bid * (1 + CTR) |
| `resetDailyBudgets()` | Cron meia-noite: zera spent_today, reativa exhausted |

### 3.9 TmsService
| Metodo | Descricao |
|--------|-----------|
| `createRoute(warehouseId, date, maxStops=30)` | Busca shipments label_created, agrupa por zona CEP, otimiza nearest neighbor |
| `assignDriver(routeId, driverId)` | Valida capacidade veiculo vs peso rota |
| `startRoute(routeId)` | Rota in_progress, shipments out_for_delivery |
| `recordDeliveryAttempt(stopId, data)` | Sucesso: POD + delivered. Falha: max 3 tentativas, depois returning |
| `updateDriverLocation(driverId, lat, lng)` | GPS cada 30s (app mobile) |
| `completeRoute(routeId)` | Libera motorista + veiculo |

### 3.10 CdSyncService
| Metodo | Descricao |
|--------|-----------|
| `syncCatalogToCd(warehouseId)` | Central -> CD: produtos com estoque |
| `syncStockFromCd(warehouseId, stockData)` | CD -> Central: atualiza stock_consolidated |
| `reconcileStock(warehouseId)` | Cron diario 03:00: compara central vs CD, registra divergencias |
| `routeToWarehouse(orderItems, shippingZipcode)` | Geo-roteamento: estoque + distancia + prioridade |

### 3.11 RulesEngineService
| Metodo | Descricao |
|--------|-----------|
| `evaluate(domain, context)` | Primeira regra que casar (short-circuit por prioridade) |
| `evaluateAll(domain, context)` | Todas que casam (dominios cumulativos) |
| **Operadores:** | ==, !=, >, >=, <, <=, in, not_in, contains, starts_with, between, is_null, not_null, is_true, is_false |
| **Dominios:** | shipping_routing, warehouse_routing, payment_gateway, free_shipping, commission, tax_calculation, ads_ranking, fraud_detection, auto_approve_return |

---

## 4. MAPA DE EVENTOS (14 eventos criticos)

```
order.created          -> OMS Worker: aguarda pagamento
payment.paid           -> OMS Worker: confirma pedido + Fiscal Worker: emite NF-e
order.splits_created   -> Stock Worker: reserva estoque por CD
stock.reserved         -> Fulfillment Worker: cria picking
picking.completed      -> Fulfillment Worker: cria shipment
shipment.shipped       -> Notification Worker: notifica cliente
shipment.delivered     -> Settlement Worker: agenda repasse D+14
fiscal.authorized      -> Notification Worker: envia DANFE
return.requested       -> Return Worker: notifica seller
return.refunded        -> Payment Worker: executa estorno
settlement.created     -> Finance Worker: transferencia PIX/TED
stock.low              -> Notification Worker: alerta seller
order.cancelled        -> Stock Worker: libera + Payment Worker: estorno
shipment.lost          -> Payment Worker: estorno automatico
```

---

## 5. GATEWAY INTERFACE

```php
interface GatewayInterface {
    public function charge(array $params): array;
    public function refund(string $gwTransactionId, float $amount): array;
    public function capture(string $gwTransactionId, float $amount): array;
    public function extractTransactionId(array $webhookPayload): string;
    public function mapWebhookToStatus(string $eventType, array $payload): string;
}
```

Implementacoes: MercadoPagoGateway, GetnetGateway (+ futuro: Stripe, Pagarme, Asaas)
