サブスクリプション、残高、価格プランの変更の処理[終了]


11

序文
私の目的は、サブスクリプションを管理するために、複数のプロジェクト用の再利用可能なコードを作成し(そしてgithubで公開することです)。ストライプと定期請求プロバイダーについては知っていますが、このモジュールが目指しているのはそれではありません。アカウントの残高を計算するためのラッパー/ヘルパー、サブスクリプションを更新するための簡単な通知、および価格計算を処理するための単なるラッパー/ヘルパーでなければなりません。

プロバイダーまたは支払いの可能性が不十分またはまったくサポートされていないか、高額すぎる(マイクロペイメント)ため、繰り返し請求を使用できない国があります。また、定期的な請求を使用したくないが、年末に請求書を手動で支払う/請求書を保存する人もいます。したがって、PayPalの定期的な請求、繰り返しまたは同様のサービスを提案しないでください。

状況
サブスクリプションプランにサブスクライブできるモデルがあるとします(例:)User。このモデルには、現在サブスクライブしているサブスクリプションプランの識別子を格納するフィールドがあります。そのため、計画が変更されるたびに、変更が記録されます。

SubscriptionPlanChanges前述の変更を記録する次のフィールドを持つモデル(など)があります。

  • subscriberサブスクライブモデルに関連する(Userこの場合)
  • from_plan モデルが変更前に持っていたプラン識別子を定義する
  • to_plan モデルが現在選択しているプラ​​ン識別子を定義する
  • created_at 変更を保存する日時フィールドです
  • valid_until 実際のサブスクリプションが有効になるまで日付を保存します
  • paid_at また、サブスクリプションが支払われたかどうか(およびいつ支払われたか)を定義する日時フィールドです。

もちろん、そのレイアウトは議論可能です。

アカウント残高の質問
ユーザーがサブスクリプションプランを変更する場合、プランフィールドを比較し、価格を取得し、現在のプランvalid_untilとその価格に基づいて新しいプランの控除を計算する必要があります。説明:プランAの1年間をサブスクライブしましたが、6か月後にプランBにアップグレードすると、プランAの6か月の支払額の半分が差し引かれます。

私が不思議に思っているのは、ユーザーが無料プランに切り替える場合など、ユーザーが再度切り替えたい場合に控除できるクレジットを持っていることです。その値を追加のフィールドにキャッシュするか、そのユーザーに関連するすべてのレコードを毎回計算しますか?テーブルのレイアウトについて何か追加/変更しますか?

わかりやすさの質問
サブスクリプション期間の終わりが来ると、ユーザーは通知を受け取り、再度支払うことでサブスクリプションを更新する可能性があります。最も簡単な方法は、更新するだけpaid_atvalid_until、新しいサブスクリプションオプションを使用することです。ただし、支払い/購読履歴など、誰かが必要とする可能性のあるすべてのデータを保存するかどうかはわかりません。

別のオプションは、このための追加レコードを作成するだろうfrom_planto_plan(したがって、「変化なし」を象徴しない)同じ識別子を持っているし。しかし、それは何らかの形で口座残高の計算を妨げませんか?

そのようなサブスクリプションを処理するロジックについて誰かが私を正しい方向に向けることができたら、とても感謝しています。


更新
今では助けてくれてありがとう。私の質問はあまりにも曖昧だったので、抽象化を少なくして、より正確になろうと思います。残念ながら、まだ問題を解決できませんでした。

ケースA
Userはを選択できますSubscription Plan A。これは現在SubscriptionPlanChange、それを追跡するために保存されます。たとえば5か月後User、サブスクリプションをにアップグレードしますSubscription Plan B。そのため、彼は新しいサブスクリプションの価格を支払い、未使用の7か月のプランaの価格を差し引きます。

ケースB
3か月後、User彼のに戻りSubscription Plan Aます。彼は支払いをする必要はありませんが、残高を受け取るので、サブスクリプションの終了時に、彼は新しいサブスクリプションのためにその残高を差し引きます。

ケースC
Userでは、独立したサブスクリプションプランを持つサブサービスのサブスクリプションプランを選択できます。同じでCase ACase Bそのサブサービスのサブスクリプションに適用できます。

_Case D_ ユーザーがサブスクリプションの1つをキャンセルします。これにより、彼のバランスが回復します。

私の質問(少なくとも現在)は、主にそのデータを適切に保存する方法に依存しているので、ビジネス分析のためにサブスクリプションの履歴を再現し、残高を計算し、サブスクリプションに基づいて未払いを得ることができます。

また、ユーザーモデル自体などに残高を保存する必要があるかどうか、または保存されていないが保存されたデータ/履歴に基づいていつでも計算できるかどうかもわかりません。

注意すべき点がいくつかありますが、問題が発生することはないと思います。

  • それはである必要はありませんUser、それは何でもありえます、それSubscriberが多形である理由です
  • Plans必ずしも計画である必要はありませんが、たとえばMagazines言及したようなものである可能性があります。それがケースCケースDで説明したことです。

1
確かにできることの1つは、各発行に価格を割り当て(プランに依存し、[plan、issue]の組み合わせが[issue price]にマッピングされるようにする)、雑誌ごとに各サブスクライバーの残高を単純に追跡することです。 (またはあなたが好む用語)。
CVn

皆さんに感謝します。まだ問題を解決できなかったため、質問を更新する必要がありました。
-pduersteler

1
どうやってこれを実装したのでしょうか?
JCM

回答:


6

残念ながら、複雑な問題に対する答えは通常複雑です。あなたへの私のアドバイスは、関連情報のみを保存し、モデルを使用して全体像を構築することです。

つまり、テーブルSubscriptionPlanChangesには、そのキーに関する次の情報が含まれます。

  • 加入者
  • 予定
  • から有効

このようにして、同じサブスクライバーに対して重複する可能性のある複数のプランを許可します。その他のフィールドは次のとおりです。

  • まで有効
  • まで支払った
  • レート(無料の場合も0)

「from from」または「plan to」がないことに注意してください。それらを使用することもできますが、情報は不要であり、自分で計算することができます(そのような情報を保存すると、一貫性を保つという追加のタスクが必要になります)。新しい計画が開始されると、既存の計画を変更するのではなく、それらを残して単純に新しいレコードを追加します。新しい計画の後に別の重複する計画が存在する場合、削除することを決定できます(この方法はより直感的です)。これらのプランをサブスクライバーにロードする場合、「有効開始日」でソートします。

これを取得すると、ユーザーのクレジットの計算は比較的簡単です。2つの計画が重複できない場合、終了日を決定するために、前の計画の「有効期限」日付と現在の計画の「有効期限」の間の2つの日付のうち小さい方を使用します。開始日は、「有効開始日」と「支払い終了日」の間の2つの日付のうち、大きい方です(定義されている場合)。次に、そのプランの上記の開始日と終了日の間の時間間隔を掛けたレートで、支払い(またはクレジット)を計算できます。

このようにして、理論的には、知る必要のあるものは何でも計算できます。既存のレコードが変更、追加、または削除されると変更されるため、計算値を保存しようとすることはお勧めしません。

これらの値の計算方法のバリエーションは、追加のタイプフィールドを追加することで管理できます。コードでは、特別なハンドラーを作成して、特定の計画を計算するロジックを管理し、メインアルゴリズムを複雑な計算から比較的明確に保つことができます。さらに、型が指定されていない場合にハンドラーを作成することができれば、必要な計算を行うために、その型に応じて適切なハンドラーを呼び出すだけで済みます。

それがあなたの質問に答えることを願っています。


多くの感謝、それはいくつかの光を当てる!「有効な」フィールドについては不明確だったように感じますが。valid_untilあなたの私の用語でしたpaid_until。購読するプランの最大長はありません。
-pduersteler

@pduerstelerああ、私の間違い。「終了」日は新しい計画の始まりにすぎないため、計算はそれほど簡単ではありません。
ニール

1
料金は支払われますか?はいの場合、これは別のエンティティ、たとえば請求書である可能性がありますか?
JCM

3

上記の答えに加えて、クレジットが現在の通貨と同じになるクレジットを持つテーブルを作成します。ユーザーがより安価な代替プランに切り替えるたびに、未使用の残高がクレジットとして入力されます。ユーザーが何か支払うものがあるときはいつでも、最初にクレジットを使用し、クレジットがなくなるか存在しない場合にのみ支払いを要求します。この代替方法を使用する場合、紛争が発生した場合に使用シナリオを再現できるように、トランザクションリストとしてテーブルを作成します。例:

ID、UserId、TransactionDate、Credit(ユーザーにクレジットを与える場合は正、ユーザーがクレジットを使用する場合は負)

ユーザーのクレジットを合計して、残高を表示します。

これがあなたの役に立つことを願っています...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.