Gestion des abonnements, des soldes et des modifications du plan tarifaire [clôturé]

11

Préambule
Mon objectif est de créer du code réutilisable pour plusieurs projets (et aussi de le publier sur github) pour gérer les abonnements. Je connais les fournisseurs de facturation récurrente et stripe, mais ce n'est pas ce que vise ce module. Il devrait simplement être un wrapper / helper pour le calcul du solde du compte, des notifications faciles pour renouveler un abonnement et gérer les calculs de prix.

Il existe des pays dans lesquels vous ne pouvez pas utiliser la facturation récurrente en raison du manque ou de l'absence de prise en charge des fournisseurs ou des possibilités de paiement ou trop chers (micropaiements). Et il y a des gens qui ne veulent pas utiliser la facturation récurrente mais qui paient leur facture manuellement / avingg une facture à la fin de l'année. Veuillez donc ne pas suggérer de facturation récurrente paypal, de services récurrents ou similaires.

Situation
Imaginons que vous disposiez d'un modèle pouvant souscrire à un plan d'abonnement (par exemple User). Ce modèle possède un champ qui stocke l'identifiant d'un plan d'abonnement auquel il est actuellement abonné. Ainsi, à chaque changement de plan, le changement est enregistré.

Il existe un modèle (par exemple SubscriptionPlanChanges) avec les champs suivants enregistrant les changements mentionnés:

  • subscriberrelative au modèle d'abonnement ( Userdans ce cas)
  • from_plan définir l'identifiant du plan du modèle avant le changement
  • to_plan définir l'identifiant du plan que le modèle a sélectionné maintenant
  • created_at est un champ date-heure stockant la modification
  • valid_until stocke la date jusqu'à ce que l'abonnement réel soit valide
  • paid_at est également un champ date-heure qui définit si (et quand) l'abonnement a été payé

Bien sûr, cette disposition est discutable.

Question du solde du compte
Lorsqu'un utilisateur modifie son plan d'abonnement, je dois comparer les champs du plan, obtenir les prix et calculer la déduction pour le nouveau plan en fonction du plan actuel valid_untilet de son prix. Dites: Vous avez souscrit pour une année de plan A mais après 6 mois, vous passez au plan B, vous obtenez donc une déduction de la moitié du prix payé pour les 6 mois du plan A.

Ce que je me demande: Si un utilisateur passe par exemple au forfait gratuit, il a un crédit qui peut être déduit si l'utilisateur veut changer de nouveau. Souhaitez-vous mettre cette valeur en cache dans un champ supplémentaire, ou calculer à travers tous les enregistrements liés à cet utilisateur à chaque fois? Souhaitez-vous ajouter / modifier quelque chose sur la disposition du tableau?

Question de facilité de compréhension
Lorsque la fin d'une période d'abonnement arrive, l'utilisateur est prévenu et a la possibilité de renouveler son abonnement en payant à nouveau. Le moyen le plus simple serait de simplement mettre à jour paid_atet valid_untilavec de nouvelles options d'abonnement. Cependant, je ne sais pas si vous stockez toutes les données dont quelqu'un pourrait avoir besoin, comme un historique de paiement / abonnement.

Une autre option serait de créer un enregistrement supplémentaire pour cela, où from_planet to_planayant le même identifiant (symbolisant ainsi "aucun changement"). Mais cela n'interférerait-il pas d'une manière ou d'une autre dans le calcul du solde du compte?

Si quelqu'un pouvait m'orienter dans la bonne direction concernant les logiques gérant de tels abonnements, je l'apprécierais beaucoup.


MISE
À JOUR Merci pour l'aide maintenant. Je pense que ma question était trop vague donc je vais essayer d'être plus précis en utilisant moins d'abstraction. Malheureusement, je n'ai pas encore pu résoudre mon problème.

Le cas A
User peut être sélectionné Subscription Plan A. Cela stocke actuellement un SubscriptionPlanChangepour en garder la trace. Après par exemple 5 mois, Usermet à niveau son abonnement vers Subscription Plan B. Il paie donc le prix de son nouvel abonnement, en déduisant le prix du plan a pour les 7 mois non utilisés.

Cas B
Après 3 mois, Userrevient au sien Subscription Plan A. Il n'a pas à payer mais reçoit un solde pour que, à la fin de l'abonnement, il soit déduit de ce solde pour son nouvel abonnement.

Le cas C
User peut sélectionner un plan d'abonnement pour un sous-service qui a des plans d'abonnement indépendants. Idem Case Aet Case Bpeut demander cet abonnement de sous-service.

_Case D_ L'utilisateur annule l'un de ses abonnements. Il en résulte un rechargement de son équilibre.

Ma question (actuellement, au moins) dépend principalement de la façon de stocker correctement ces données afin que je puisse reproduire un historique des abonnements pour l'analyse commerciale et calculer les soldes, obtenir des paiements en cours en fonction des abonnements, etc.

Je ne sais pas non plus si le solde doit être stocké dans, par exemple, le modèle utilisateur lui-même, ou s'il n'est pas stocké mais peut être calculé à tout moment en fonction des données / de l'historique stockés.

Certaines choses à noter, bien que je ne pense pas qu'elles devraient introduire des problèmes:

  • Il n'est pas nécessaire que ce soit un User, cela pourrait être n'importe quoi, c'est pourquoi le Subscriberpolymorphe est
  • Plansne doivent pas nécessairement être des plans, mais pourraient être par exemple Magazinescomme mentionné. Voilà ce que je viens de décrire avec l' affaire C et Type D .
pduersteler
la source
1
Une chose que vous pourriez certainement faire serait d'attribuer à chaque numéro un prix (qui peut dépendre du plan de telle sorte que la combinaison [plan, numéro] mappe sur [prix d'émission]), puis de simplement suivre le solde de chaque abonné par magazine (ou selon la terminologie que vous préférez).
un CVn le
Merci à tous, j'avais besoin de mettre à jour la question car je ne pouvais pas encore résoudre mon problème.
pduersteler
1
Puis-je vous demander comment vous avez fini par mettre cela en œuvre?
JCM

Réponses:

6

Malheureusement, la réponse à un problème compliqué est généralement compliquée. Je vous conseillerais de ne conserver que les informations pertinentes, puis d'utiliser un modèle pour construire une vue d'ensemble.

En d'autres termes, votre table SubscriptionPlanChanges aurait les informations suivantes pour sa clé:

  • abonné
  • plan
  • Valide à partir de

De cette façon, vous autorisez plusieurs plans pour le même abonné qui peuvent se chevaucher. Les autres domaines comprennent:

  • valable jusque
  • payé jusqu'à
  • taux (également 0 si gratuit)

Notez qu'il n'y a pas de "plan de" ou "plan de". Bien que vous puissiez les avoir, les informations sont superflues et peuvent être calculées par vous-même (le stockage de ces informations signifie que vous avez la tâche supplémentaire de les garder cohérentes). Lorsqu'un nouveau plan commence, plutôt que d'avoir à modifier des plans existants, vous les laissez et ajoutez simplement un nouvel enregistrement. Si un autre plan se chevauche après le nouveau plan, vous pouvez alors décider de le supprimer (plus intuitif de cette façon). Lorsque vous chargez ces plans pour un abonné, vous les triez par date de "validité à partir de".

Une fois que vous avez obtenu cela, le calcul du crédit d'un utilisateur est relativement simple. Si deux plans ne peuvent pas se chevaucher, il vous suffit de prendre la moindre des deux dates entre la date "valable jusqu'au" du plan précédent et la "valable du" du plan actuel afin de déterminer la date de fin. La date de début est la plus grande des deux dates entre la date "valable du" et la date "payé jusqu'au" (si définie). Le paiement (ou crédit) peut alors être calculé sur le taux multiplié par l'intervalle de temps entre les dates de début et de fin susmentionnées de ce plan.

De cette façon, vous pouvez en théorie calculer tout ce que vous devez savoir. Je déconseille d'essayer de sauvegarder les valeurs calculées, car cela changerait lorsqu'un enregistrement existant est modifié, ajouté ou supprimé.

Les variations de la façon dont vous calculeriez ces valeurs peuvent être gérées en ajoutant un champ de type supplémentaire. Dans votre code, vous pouvez créer des gestionnaires spéciaux pour gérer la logique de calcul de plans particuliers afin de garder votre algorithme principal relativement clair des calculs compliqués. Mieux encore, si vous parvenez à créer un gestionnaire pour le cas où aucun type n'est spécifié, tout ce que vous avez à faire est d'appeler le gestionnaire approprié en fonction de son type afin d'effectuer tout type de calcul dont vous avez besoin.

J'espère que cela répond à votre question.

Neil
la source
Merci beaucoup, cela a fait la lumière! Bien que j'ai l'impression de ne pas être clair sur le champ "valide". valid_untilétait ma terminologie de votre paid_until. Il n'y a pas de durée maximale pour un abonnement.
pduersteler
@pduersteler Ah mon erreur alors. Cela ne fait que faciliter le calcul, car la date de «fin» n'est que le début du nouveau plan.
Neil
1
Quel est le montant payé? Si oui, cela pourrait être une autre entité, une facture par exemple, ai-je raison?
JCM
3

En plus de la réponse ci-dessus, je créerais un tableau avec des crédits, où un crédit serait égal à la devise actuelle. Chaque fois que l'utilisateur change de plan pour une alternative moins chère, le solde inutilisé entre en tant que crédits. Chaque fois que l'utilisateur a quelque chose à payer, vous utiliserez d'abord les crédits et ne demanderez le paiement que si les crédits sont épuisés ou n'existent pas. Si vous utilisez cette alternative, créez la table en tant que liste de transactions afin de pouvoir reproduire le scénario d'utilisation en cas de litige. Exemple:

ID, UserId, TransactionDate, Credit (positif lorsque vous attribuez des crédits à l'utilisateur et négatif lorsque l'utilisateur utilise le crédit)

Additionnez simplement les crédits de l'utilisateur pour lui montrer le solde.

J'espère que cela vous sera utile ...

Lars Hofvander
la source