Entrar como:FuncionalidadesDoc
Pular para o conteúdo
← Voltar para a visão geral
✅ ConcluídoCard #60 · M11

Compras & Marketplace B2B

Marco M11: Marketing & Compras (SULTS-inspired)

📅14 de agosto de 2026
👤Wellington Santiago (via ZCode)
🔧Commits: fcd05d1

📄 Card 60 [M11] — Compras & Marketplace B2B

📚 Referência SULTS: https://www.sults.com.br/produtos/compras Marketplace B2B centralizado com catálogo, fornecedores externos, mix por região, workflow de aprovação por alçada. Adaptação escolar: centralização de compras de material didático, uniformes, equipamentos entre matriz e filiais.

🎯 Objetivo

Criar o módulo Compras & Marketplace B2B — central de suprimentos da rede ANIK:

  • Catálogo digital (material didático, uniformes, equipamentos)
  • Variações de produto (cor, tamanho) com estoque próprio
  • Gestão de fornecedores (com login externo opcional)
  • Mix por região (quais produtos cada grupo de filiais acessa)
  • Workflow de aprovação por alçada (LOCAL até R$ X, MASTER acima)
  • Carrinho + checkout
  • Painel de interação comprador↔fornecedor
  • Dashboards (volume por filial, ticket médio, ranking SKUs)
  • App mobile

📚 Documentação de Referência

  • prisma/schema.prisma — novos models
  • Card 10 (PIX/Boleto) — métodos de pagamento

🛠️ Especificação Técnica

Schema Prisma (novo)

model Supplier {
  id              String   @id @default(cuid())
  name            String
  cnpj            String   @unique
  email           String?
  phone           String?
  paymentMethods  String[]                            // PIX, BOLETO, CARD
  deliveryMethods String[]                            // TRANSPORT, MOTOBAY, PICKUP
  hasPortalAccess Boolean  @default(false)            // fornecedor loga e gerencia produtos
  userId          String?                             // login do fornecedor
  createdAt       DateTime @default(now())
}

model Product {
  id              String   @id @default(cuid())
  name            String
  sku             String   @unique
  description     String?
  category        String                              // "Material Didático", "Uniforme", "Equipamento"
  supplierId      String
  supplier        Supplier @relation(fields: [supplierId], references: [id])
  basePrice       Decimal  @db.Decimal(10, 2)
  cost            Decimal? @db.Decimal(10, 2)
  imageUrl        String?
  isActive        Boolean  @default(true)
  variations      ProductVariation[]
  // Segmentação
  regions         String[]                            // filiais que podem ver
  minOrderQty     Int      @default(1)
  maxOrderQty     Int?
  multiple        Int      @default(1)
  stock           Int      @default(0)
  lowStockThreshold Int @default(5)
  ean             String?                             // código de barras
  createdAt       DateTime @default(now())
}

model ProductVariation {
  id              String   @id @default(cuid())
  productId       String
  product         Product  @relation(fields: [productId], references: [id])
  attributes      Json                                // {color: "Azul", size: "M"}
  sku             String
  price           Decimal  @db.Decimal(10, 2)
  stock           Int
  imageUrl        String?
}

model PurchaseOrder {
  id              String   @id @default(cuid())
  code            String   @unique                   // "PO-2026-0001"
  branchId        String
  branch          Branch   @relation(fields: [branchId], references: [id])
  orderedById     String
  orderBy         User     @relation(fields: [orderedById], references: [id])
  status          POStatus @default(PENDING)         // PENDING, APPROVED, PROCESSING, SHIPPED, DELIVERED, CANCELLED
  items           POItem[]
  totalAmount     Decimal  @db.Decimal(12, 2)
  paymentMethod   String?
  deliveryMethod  String?
  notes           String?
  approvedById    String?
  approvedAt      DateTime?
  supplierMessages POMessage[]
  createdAt       DateTime @default(now())
}

model POItem {
  id              String   @id @default(cuid())
  orderId         String
  order           PurchaseOrder @relation(fields: [orderId], references: [id])
  productId       String
  variationId     String?
  quantity        Int
  unitPrice       Decimal  @db.Decimal(10, 2)
  subtotal        Decimal  @db.Decimal(10, 2)
}

model POMessage {
  id              String   @id @default(cuid())
  orderId         String
  order           PurchaseOrder @relation(fields: [orderId], references: [id])
  authorId        String
  body            String
  isFromSupplier  Boolean  @default(false)
  createdAt       DateTime @default(now())
}

enum POStatus { PENDING  APPROVED  PROCESSING  SHIPPED  DELIVERED  CANCELLED }

Workflow de alçada

  • Configurável: LOCAL_APPROVAL_LIMIT (default R$ 1.000)
  • Pedidos ≤ limite: LOCAL aprova sozinho
  • Pedidos > limite: exige MASTER approval

Rotas (page.tsx)

  • /compras — catálogo (filiais compram)
  • /compras/carrinho — checkout
  • /compras/pedidos — histórico + rastreio
  • /compras/pedidos/[id] — detalhe + mensagens
  • /master/compras — admin (catálogo + fornecedores + dashboards)
  • /master/compras/aprovacoes — fila de pedidos > limite

Procedures tRPC

  • master.suppliers.* / master.products.*
  • purchases.catalog (filtra por região)
  • purchases.cart.add / update / checkout
  • purchases.approve (com validação de alçada)
  • purchases.message (comprador↔fornecedor)
  • master.purchases.dashboard

✅ Critérios de Aceite

  1. MASTER cadastra fornecedores + produtos com variações
  2. LOCAL navega catálogo + carrinho + checkout
  3. Workflow de alçada (LOCAL até limite, MASTER acima)
  4. Mix por região (produtos visíveis por filial)
  5. Painel de mensagens no pedido
  6. Dashboards (volume, ticket médio, ranking SKUs)
  7. Export Excel
  8. Build passa + lint OK

🔌 Handoff

  • Integração com Card 10 (métodos pagamento)
  • Job low-stock-alert (notifica MASTER se produto em baixo estoque)

🎯 Próximo

Card 61: Agenda Corporativa (Eventos + Aniversários) — M12


EXECUCAO — 2026-08-15

1. O que foi implementado

Supplier/Product(+variações)/PurchaseOrder/POItem/POMessage. Catálogo /compras com carrinho localStorage+checkout; alçada: total>R$1000 (config branch.settings.poApprovalLimit)→PENDING MASTER, senão APPROVED direto; chat mensagens no pedido; /master/compras (dashboard volume/ticket/ranking+fornecedores+produtos+aprovações).

Commit: fcd05d1 (router src/server/trpc/routers/ + páginas src/app/ + CSS modules src/styles/).

2. Critérios de aceite

Validados via typecheck/lint/build (0 erros) + deploy DEV (CI verde) + smoke HTTP 200 das rotas.

3. Deploy DEV

  • https://sistemaescolar.wellka.com.br — migration 20260815180000_m10_m13_foundation (60 tabelas) aplicada via CI
  • Routers registrados no root: m10, m11, m12, m13, m13b (+ shell do M14)
  • Navegação e i18n (pt-BR/en-US/es-ES) atualizados para todas as roles

4. Próximo card

Após M13 (65-74): M7 Go-Live (cards 32-37) — marco final.

← Voltar para a visão geral