Negócio

Assinaturas

Planos de assinatura, ciclos de cobranca, trial, renovacao automatica e gestao administrativa.

Assinaturas

O modulo de assinaturas controla o acesso dos usuarios aos recursos da plataforma AgrSis. Cada usuario possui uma assinatura vinculada a um plano, que define limites e funcionalidades disponiveis.

Tipos de plano

Os planos sao segmentados por perfil de usuario (profile_type): producer, supplier ou consultant.

Plano gratuito

  • Todos os precos (price_monthly, price_quarterly, price_yearly) sao null.
  • Serve como ponto de partida e como fallback quando uma assinatura paga expira ou e cancelada.
  • Pode ser marcado como is_default para ser atribuido automaticamente no cadastro.
  • Nao possui periodo de vigencia (current_period_end fica null).

Plano pago

  • Possui ao menos um preco definido entre mensal, trimestral ou anual.
  • Cada plano tem uma lista de features (tabela plan_feature_values) com valores especificos — tipo limit (numero) ou boolean.
  • O admin pode criar, editar, ativar/desativar e reordenar planos pelo painel.

Trial

Quando o plano padrao possui trial_days > 0, o usuario recebe a assinatura com status trial.

  • O valor padrao de trial e configuravel por plano (campo trial_days na tabela subscription_plans).
  • trial_ends_at e calculado como now() + trial_days.
  • current_period_end e igual a trial_ends_at durante o trial.
  • Notificacoes de expiracao sao enviadas nos dias 7, 3, 1 e 0 antes do vencimento do trial.
  • Ao expirar, o status muda para expired e o usuario e movido para o plano gratuito com status expired (fallback).

Prorrogacao de trial (admin)

O administrador pode prorrogar o trial via endpoint POST /api/v1/admin/subscriptions/{id}/extend-trial:

  • Aceita assinaturas com status trial ou expired.
  • Parametro days (1 a 365).
  • Se a assinatura estiver expirada, o novo prazo parte de now().
  • Se estiver em trial, o prazo e somado ao trial_ends_at atual.

Ciclos de cobranca

Ao assinar um plano pago, o usuario escolhe um ciclo (billing_cycle):

CicloChaveDuracao do periodo
Mensalmonthly1 mes
Trimestralquarterly3 meses
Anualyearly12 meses

O preco e determinado pelo metodo getPriceForCycle() do modelo SubscriptionPlan, que retorna o campo correspondente (price_monthly, price_quarterly ou price_yearly).

Metodos de pagamento

Os metodos habilitados sao configurados na tabela de settings (chave payment_methods_enabled) e podem incluir:

  • PIX (pix) — gera cobranca com QR Code e copia-e-cola; vencimento em 1 dia.
  • Boleto (boleto) — gera boleto com vencimento em 3 dias.
  • Cartao de credito (credit_card) — cobranca imediata; pagamento marcado como paid na hora.

Todos os pagamentos sao processados via ASAAS (classe AsaasGateway), que implementa a interface PaymentGatewayInterface. O gateway so e ativado se as chaves asaas_enabled e asaas_api_key estiverem configuradas nas settings.

Ambientes do ASAAS

  • Sandbox: https://sandbox.asaas.com/api/v3 (setting asaas_environment = sandbox)
  • Producao: https://api.asaas.com/api/v3 (setting asaas_environment = production)

Tokenizacao de cartao

Na primeira cobranca com cartao de credito, o ASAAS retorna um creditCardToken. Esse token e salvo na assinatura junto com os ultimos 4 digitos (card_last_digits) e a bandeira (card_brand).

Nas renovacoes seguintes, a cobranca e feita usando apenas o token, sem necessidade de reenviar os dados completos do cartao. O payload enviado ao ASAAS contem somente creditCardToken.

Renovacao automatica

O campo auto_renew (padrao true) controla se a assinatura sera renovada automaticamente. O processamento e feito pelo comando agendado subscriptions:process-renewals.

Alerta 7 dias antes

  • Assinaturas ativas com auto_renew = true e current_period_end igual a now() + 7 dias recebem uma notificacao.
  • Se o usuario possui cartao tokenizado, a mensagem informa que a renovacao sera automatica (ex.: "sera renovada via cartao final 1234").
  • Sem token, a mensagem orienta o usuario a renovar manualmente.

Cobranca no dia do vencimento

No dia em que current_period_end <= now():

  1. Com token de cartao: a cobranca e feita automaticamente via generateCardPayment usando o token. O periodo e renovado (current_period_start = now(), current_period_end calculado pelo ciclo). O usuario recebe notificacao de renovacao com o valor e os ultimos digitos do cartao.
  2. Sem token: o usuario recebe notificacao orientando a renovar manualmente pelo portal.
  3. Falha na cobranca: o usuario recebe notificacao de falha e e orientado a renovar manualmente.

Uma verificacao de duplicata impede que pagamentos sejam criados se ja existe um pagamento pending ou paid nos ultimos 3 dias para a mesma assinatura.

Desativar renovacao

O usuario pode desativar a renovacao automatica via:

  • POST /api/v1/subscription/cancel — desativa auto_renew sem cancelar a assinatura imediatamente.
  • POST /api/v1/subscription/toggle-auto-renew — alterna o valor de auto_renew.

Ao desativar, o plano continua ativo ate o fim do periodo pago (current_period_end). Quando o periodo expira com auto_renew = false, o sistema move o usuario para o plano gratuito.

Fallback para plano gratuito

Quando uma assinatura paga expira ou e cancelada, o metodo fallbackToFreePlan() cria uma nova assinatura no plano gratuito do mesmo profile_type, com status expired.

Situacoes que disparam o fallback:

  • Trial expirado
  • Assinatura paga expirada com auto_renew = false
  • Cancelamento apos estorno de pagamento

Webhook de pagamento

O endpoint de webhook recebe eventos do ASAAS e atualiza o status do pagamento:

Evento ASAASStatus interno
PAYMENT_CONFIRMED, PAYMENT_RECEIVEDpaid
PAYMENT_OVERDUEpast_due
PAYMENT_DELETED, PAYMENT_RESTOREDcancelled
PAYMENT_REFUNDEDrefunded

Quando o pagamento e confirmado (paid), a assinatura e ativada e o periodo e renovado. Quando fica atrasado (past_due), o status da assinatura muda para past_due e o usuario e notificado.

Gestao administrativa

O painel administrativo oferece os seguintes recursos:

Planos

  • Listar planos com contagem de assinantes (GET /api/v1/admin/subscription-plans)
  • Criar plano com nome, perfil, precos e trial days (POST /api/v1/admin/subscription-plans)
  • Editar plano incluindo marcar como default (PUT /api/v1/admin/subscription-plans/{id})
  • Gerenciar features de cada plano (PUT /api/v1/admin/subscription-plans/{id}/features)
  • Desativar plano — soft delete via is_active = false (DELETE /api/v1/admin/subscription-plans/{id})

Ao marcar um plano como is_default, todos os outros planos do mesmo profile_type sao desmarcados.

Assinaturas

  • Listar assinaturas com filtro por status e paginacao (GET /api/v1/admin/subscriptions)
  • Alterar plano de uma assinatura com observacao obrigatoria e registro em audit log (PUT /api/v1/admin/subscriptions/{id}/change-plan)
  • Ativar manualmente uma assinatura por N dias, com observacao obrigatoria e auto_renew = false (POST /api/v1/admin/subscriptions/{id}/activate)
  • Prorrogar trial de 1 a 365 dias (POST /api/v1/admin/subscriptions/{id}/extend-trial)
  • Historico de acoes administrativas via audit log (GET /api/v1/admin/subscriptions/{id}/logs)

Pagamentos

  • Listar pagamentos com filtro por status (GET /api/v1/admin/subscription-payments)
  • Estornar pagamento total ou parcial via ASAAS, com opcao de cancelar a assinatura (POST /api/v1/admin/subscription-payments/{id}/refund)
    • So permite estorno de pagamentos com status paid
    • Valor parcial nao pode exceder o valor pago
    • Se cancel_subscription = true, a assinatura e cancelada e o usuario cai no plano gratuito

Metricas do dashboard

O endpoint GET /api/v1/admin/subscription-metrics retorna:

  • Assinantes ativos (trial + active)
  • Contagem separada de trials e pagos ativos
  • Assinaturas expiradas
  • Receita do mes atual
  • ARR (Annual Recurring Revenue) — soma anualizada das assinaturas ativas pagas
  • Assinaturas expirando neste mes e no proximo
  • Historico de receita dos ultimos 6 meses

Notificacoes

As notificacoes de assinatura sao enviadas via sistema interno e, conforme configuracao do NotificationChannelConfig, podem ser encaminhadas por email e/ou WhatsApp.

TipoQuando
trial_expiring7, 3, 1 e 0 dias antes do fim do trial
trial_expiredTrial expirou
payment_confirmedPagamento confirmado (webhook ou cartao)
payment_overduePagamento atrasado
subscription_renewedAssinatura renovada automaticamente
subscription_charge_createdAlerta 7 dias antes do vencimento / renovar

Status da assinatura

StatusSignificado
trialPeriodo de teste ativo
activeAssinatura paga ativa
past_duePagamento atrasado
expiredPeriodo encerrado (trial ou pago)
cancelledCancelada manualmente ou por estorno

Comandos agendados

ComandoFuncao
subscriptions:process-renewalsAlerta 7 dias antes e renova assinaturas no dia do vencimento
Verificacao de expiradosExecutada pelo metodo checkExpired() do SubscriptionService, que expira trials e assinaturas com auto_renew = false
Copyright © 2026