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:
subscriber
relative au modèle d'abonnement (User
dans ce cas)from_plan
définir l'identifiant du plan du modèle avant le changementto_plan
définir l'identifiant du plan que le modèle a sélectionné maintenantcreated_at
est un champ date-heure stockant la modificationvalid_until
stocke la date jusqu'à ce que l'abonnement réel soit validepaid_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_until
et 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_at
et valid_until
avec 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_plan
et to_plan
ayant 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 SubscriptionPlanChange
pour en garder la trace. Après par exemple 5 mois, User
met à 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, User
revient 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 A
et Case B
peut 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 leSubscriber
polymorphe est Plans
ne doivent pas nécessairement être des plans, mais pourraient être par exempleMagazines
comme mentionné. Voilà ce que je viens de décrire avec l' affaire C et Type D .
Réponses:
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é:
De cette façon, vous autorisez plusieurs plans pour le même abonné qui peuvent se chevaucher. Les autres domaines comprennent:
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.
la source
valid_until
était ma terminologie de votrepaid_until
. Il n'y a pas de durée maximale pour un abonnement.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 ...
la source