Manipulação de assinaturas, saldos e alterações no plano de preços [fechado]


11

Preâmbulo
Meu objetivo é criar código reutilizável para vários projetos (e também publicá-lo no github) para gerenciar assinaturas. Eu sei sobre provedores de cobrança recorrente e de distribuição, mas não é para isso que este módulo se destina. Deve ser apenas um invólucro / auxiliar para calcular o saldo da conta, notificações fáceis para renovar uma assinatura e gerenciar cálculos de preços.

Existem países em que você não pode usar o faturamento recorrente por causa dos provedores ou possibilidades de pagamento terem pouco ou nenhum suporte ou são muito caros (micropagamentos). E há pessoas que não desejam usar o faturamento recorrente, mas pagam a fatura manualmente / pagam uma fatura no final do ano. Portanto, não sugira cobrança recorrente por paypal, serviços recorrentes ou similares.

Situação
Digamos que você tenha um modelo que possa se inscrever em um plano de assinatura (por exemplo User). Este modelo possui um campo que armazena o identificador de um plano de assinatura no qual ele está atualmente inscrito. Assim, em cada mudança de plano, a mudança é registrada.

Existe um modelo (por exemplo SubscriptionPlanChanges) com os seguintes campos registrando as alterações mencionadas:

  • subscriberrelacionado ao modelo de assinatura ( Userneste caso)
  • from_plan definindo o identificador do plano que o modelo tinha antes da mudança
  • to_plan definindo o identificador de plano que o modelo selecionou agora
  • created_at é um campo de data e hora que armazena a alteração
  • valid_until armazena a data até a assinatura real ser válida
  • paid_at também é um campo de data e hora que define se (e quando) a assinatura foi paga

Claro, esse layout é discutível.

Questão do saldo da conta
Quando um usuário altera seu plano de assinatura, preciso comparar os campos do plano, obter os preços e calcular a dedução do novo plano com base nos valid_untilpreços e no plano atual . Diga: você se inscreveu para um ano do plano A, mas após 6 meses, atualiza para o plano B, obtendo uma dedução de metade do preço pago pelos 6 meses do plano A.

O que estou me perguntando: se um usuário, por exemplo, muda para o plano gratuito, ele tem um crédito que pode ser deduzido se o usuário quiser mudar novamente. Você armazenaria esse valor em cache em um campo adicional ou calcularia todos os registros relacionados a esse usuário todas as vezes? Você adicionaria / alteraria algo sobre o layout da tabela?

Questão de fácil compreensão
Quando chega o final de um período de assinatura, o usuário é notificado e tem a possibilidade de renovar sua assinatura pagando novamente. A maneira mais fácil seria apenas atualizar paid_ate valid_untilcom novas opções de assinatura. No entanto, não tenho certeza se você armazena todos os dados que alguém possa precisar, como um histórico de pagamento / assinatura.

Outra opção seria criar um registro adicional para isso, onde from_plane to_planesteja tendo o mesmo identificador (simbolizando, assim, "nenhuma alteração"). Mas isso não interferiria no cálculo do saldo da conta de alguma maneira?

Se alguém pudesse me indicar a direção certa sobre as lógicas que lidam com essas assinaturas, eu agradeceria muito.


ATUALIZAÇÃO
Obrigado pela ajuda até agora. Eu acho que minha pergunta foi muito vaga, então tentarei ser mais preciso usando menos abstração. Infelizmente, ainda não consegui resolver o meu problema.

O caso A
User pode selecionar Subscription Plan A. Atualmente, ele armazena um SubscriptionPlanChangepara acompanhar isso. Após, por exemplo, 5 meses, Useratualiza sua assinatura para Subscription Plan B. Portanto, ele paga o preço de sua nova assinatura, deduzindo o preço do plano a pelos sete meses não utilizados.

Caso B
Após 3 meses, Uservolta para o dele Subscription Plan A. Ele não precisa pagar, mas recebe um saldo para que, ao final da assinatura, obtenha esse saldo deduzido para sua nova assinatura.

O Caso C
User pode selecionar um plano de assinatura para um sub-serviço que possui planos de assinatura independentes. O mesmo Case Ae Case Bpode aplicar-se a essa assinatura de sub-serviço.

_Case D_ O usuário cancela uma de suas assinaturas. Isso resulta em uma recarga de seu saldo.

Minha pergunta (atualmente, pelo menos) depende principalmente de como armazenar esses dados corretamente, para que eu possa reproduzir um histórico de assinaturas para análise de negócios e calcular saldos, obter pagamentos pendentes com base nas assinaturas etc.

Também não tenho certeza se o saldo deve ser armazenado, por exemplo, no próprio modelo do usuário ou se não está armazenado, mas pode ser calculado a qualquer momento com base nos dados / histórico armazenados.

Algumas coisas a serem observadas, embora eu não ache que elas devam apresentar problemas:

  • Não precisa ser um User, pode ser qualquer coisa, é por isso que Subscriberé polimórfico
  • Plansnão necessariamente precisam ser planos, mas podem ser, por exemplo, os Magazinesmencionados. Isso é o que eu descrevi com processo C e Caixa D .

1
Uma coisa que você certamente poderia fazer seria atribuir um preço a cada edição (que pode ser dependente do plano, de modo que a combinação [plano, emissão] seja mapeada para [preço de emissão]) e simplesmente acompanhar o saldo de cada assinante por revista (ou qualquer terminologia que você preferir).
um CVn

Obrigado a todos, eu precisava atualizar a pergunta, porque ainda não consegui resolver o meu problema.
Pduersteler

1
Posso perguntar como você acabou implementando isso?
JCM

Respostas:


6

Infelizmente, a resposta para um problema complicado geralmente é complicada. Meu conselho a você seria salvar apenas informações relevantes e usar um modelo para construir a imagem maior.

Em outras palavras, sua tabela SubscriptionPlanChanges teria as seguintes informações para sua chave:

  • assinante
  • plano
  • válido de

Dessa forma, você permite vários planos para o mesmo assinante que podem se sobrepor. Outros campos incluem:

  • válido até
  • pago até
  • taxa (também 0 se gratuito)

Observe que não há "plano de" ou "plano para". Embora você possa tê-las, as informações são supérfluas e podem ser calculadas por conta própria (armazenar essas informações significa que você tem a tarefa adicional de mantê-las consistentes). Quando um novo plano começa, em vez de precisar modificar os planos existentes, você os deixa e simplesmente adiciona um novo registro. Se existir outro plano sobreposto após o novo plano, você poderá decidir excluí-lo (mais intuitivo dessa maneira). Ao carregar esses planos para um assinante, você os classifica pela data "válido de".

Depois de obter isso, calcular o crédito de um usuário é relativamente simples. Se dois planos não puderem se sobrepor, basta levar a menor das duas datas entre a data "válida até" do plano anterior e a "válida de" do plano atual para determinar a data final. A data de início é a maior das duas datas entre a data "válida de" e a data "paga até" (se definida). O pagamento (ou crédito) pode então ser calculado sobre a taxa multiplicada pelo intervalo de tempo entre as datas de início e término mencionadas acima desse plano.

Dessa forma, você pode, em teoria, calcular o que precisa saber. Eu desaconselharia a tentativa de salvar valores calculados, pois isso mudaria quando um registro existente é modificado, adicionado ou excluído.

Variações de como você calcularia esses valores podem ser gerenciadas adicionando um campo de tipo adicional. No seu código, você pode criar manipuladores especiais para gerenciar a lógica do cálculo de planos específicos, a fim de manter seu algoritmo principal relativamente livre de cálculos complicados. Melhor ainda, se você conseguir criar um manipulador para o caso em que nenhum tipo seja especificado, portanto, tudo o que você precisa fazer é chamar o manipulador apropriado de acordo com seu tipo para fazer qualquer tipo de cálculo necessário.

Espero que isso responda à sua pergunta.


Muito obrigado, que lançou alguma luz! Embora eu sinta que não tenho certeza sobre o campo "válido". valid_untilfoi a minha terminologia sua paid_until. Não há um comprimento máximo de um plano para se inscrever.
Pduersteler #

@ pduersteler Ah meu erro então. Isso apenas facilita muito o cálculo, uma vez que a data "final" é apenas o começo do novo plano.
29513 Neil

1
Taxa é o valor pago? Se sim, então poderia ser outra entidade, uma fatura, por exemplo, estou certo?
JCM

3

Além da resposta acima, eu criaria uma tabela com créditos, onde um crédito seria igual à moeda atual. Sempre que o usuário alterna o plano para uma alternativa mais barata, o saldo não utilizado entra como créditos. Sempre que o usuário tiver algo a pagar, você deverá usar os créditos primeiro e solicitar o pagamento apenas se os créditos acabarem ou não existirem. Se estiver usando essa alternativa, crie a tabela como uma lista de transações para poder reproduzir o cenário de uso, se alguma disputa ocorrer. Exemplo:

ID, ID do usuário, Data da transação, Crédito (positivo quando você dá créditos ao usuário e negativo quando o usuário usa o crédito)

Basta somar os créditos para o usuário mostrar o saldo.

Espero que isso seja útil para você ...

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.