Pular para conteúdo

Campanhas, Premium e indicação

Campanhas

Campanhas são administradas pelo Super Admin. O backend aceita a matriz:

stateDiagram-v2
    [*] --> draft
    draft --> scheduled
    draft --> open_for_partners
    draft --> cancelled
    scheduled --> open_for_partners
    scheduled --> active
    scheduled --> cancelled
    open_for_partners --> active
    open_for_partners --> cancelled
    active --> ended
    active --> cancelled
    ended --> archived

createCampaign sempre cria em draft. updateCampaign só altera campanhas draft|scheduled. changeCampaignStatus valida a matriz em transação; ao encerrar, expira ofertas de campanha active|approved em lotes de até 400.

Dois schedulers completam o ciclo temporal:

  • autoTransitionCampaigns: scheduled → open_for_partners quando começa a submissão e scheduled|open_for_partners → active no início da campanha;
  • closeExpiredCampaigns: active → ended ao atingir campaignEndAt, seguido da expiração das ofertas relacionadas.

Ambos são acionados a cada minuto, mas respeitam os intervalos configurados em settings/schedulers.

Participação do parceiro

joinCampaign deriva o partner pelo owner_uid, exige campanha aberta e grava o ID determinístico {campaignId}_{partnerId} como interested. withdrawCampaignParticipation impede desistência de participação approved.

submitCampaignOffer exige janela de submissão aberta, participação existente, ownership de todas as unidades e payload coerente com discount ou buyMore. Cria uma oferta por unidade com:

  • source: campaign;
  • status: pending_review;
  • visibilityTier: free;
  • campaignId, partnerId e restaurantId derivados/validados;
  • participação atualizada para submitted no mesmo batch.

Premium com Stripe

O acesso pago segue o webhook como fonte de verdade:

sequenceDiagram
    participant App
    participant CF as Cloud Functions
    participant Stripe
    participant DB as Firestore

    App->>CF: createStripeCheckoutSession(plan)
    CF->>Stripe: cria/recupera customer e Checkout Session
    CF-->>App: URL da sessão
    Stripe->>CF: stripeWebhook assinado
    CF->>DB: reserva stripeEvents/{eventId}
    CF->>DB: sincroniza subscriptions/{uid} e users/{uid}

Planos aceitos: premium_monthly e premium_launch. Os estados active|trialing concedem premiumAccessSource: subscription; estados não ativos removem essa origem se ela ainda for subscription.

Eventos processados:

  • checkout.session.completed;
  • invoice.paid;
  • invoice.payment_failed;
  • customer.subscription.created|updated|deleted.

stripeEvents reserva o ID em transação e impede processamento concorrente/duplicado. Checkout, Portal e webhook exigem os segredos descritos em Configuração.

Indicação

submitReferralCode normaliza o código, proíbe autoindicação e troca de código. Se phone_verified já for verdadeiro, aplica a recompensa imediatamente; caso contrário, aguarda o trigger de criação/atualização do usuário.

referralEngine executa transação, procura o indicador, impede duplicidade pelo par indicador/convidado, cria uma recompensa disponível e marca referralRewardClaimed. O fluxo também grava audit_referrals, inacessível diretamente pelos clientes.

Recompensas compatíveis podem autorizar um único cupom Premium quando o usuário não possui assinatura/admin grant. A geração do cupom reserva e consome a recompensa na mesma transação.

Exclusão de conta

deleteUserAccount exige autenticação e pode cancelar assinatura Stripe ativa. Dados pessoais são excluídos ou redigidos em lotes/transações; histórico financeiro e operacional é preservado de forma redigida quando necessário. Para conta de parceiro, integrações, garçons, sessões, unidades e documento do partner são removidos, enquanto cupons/ofertas são redigidos.

Storage

O código remove referências de imagem de documentos durante a exclusão, mas a remoção física segura dos objetos no Storage permanece pendente na implementação. Não trate a exclusão do documento como prova de remoção do arquivo.