From 3bc2114c0278646cdd98fed5383d0bb5fea15f9b Mon Sep 17 00:00:00 2001 From: Pierre Spring Date: Mon, 10 Aug 2020 17:32:12 +0200 Subject: [PATCH 1/5] propose accounting for subscription --- concept/membership-v2.md | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 concept/membership-v2.md diff --git a/concept/membership-v2.md b/concept/membership-v2.md new file mode 100644 index 0000000..26a7706 --- /dev/null +++ b/concept/membership-v2.md @@ -0,0 +1,62 @@ +# Membership V2 + +```md +user +---- +id + +subscription credit +------------------- +id +user_id +credit, INT, Amount of days +createdAt + +subscription debit +------------------ +user_id +debit +createdAt Date +endedAt NULL | Date + +CONSTRAINT "only one active subscription" UNIQUE(user.id, endedAt) + +payment history +--------------- +price +product, enum(ABO, BENEFACTOR_ABO, MONTHLY_ABO, ABO_GIVE_MONTHS) +subscription.id +``` + +## Queries + +```SQL +# is active +SELECT + COUNT(*) > 0 AS is_active +FROM + subscription_debit +WHERE + user_id = $userId +AND + endedAt = NULL +GROUP BY + user_id; + +# balance +SELECT + subscription_credit.user_id, + SUM(subscription_credit.credit) AS "sum_credit", + SUM(subscription_debit.debit) AS "sum_debit", + (sum_credit - sum_debit) AS balance +FROM + subscription_credit +INNER JOIN + subscription_debit +ON + subscription_credit.user_id = subscription_debit.user_id +WHERE + user_id = $user_id +GROUP BY + user_id +``` \ No newline at end of file From e2cf0213d2409e628116d791871cd0d05fc86bad Mon Sep 17 00:00:00 2001 From: Pierre Spring Date: Mon, 10 Aug 2020 18:06:28 +0200 Subject: [PATCH 2/5] add auto_renew and current_product to user --- concept/membership-v2.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/concept/membership-v2.md b/concept/membership-v2.md index 26a7706..19ddb84 100644 --- a/concept/membership-v2.md +++ b/concept/membership-v2.md @@ -4,6 +4,9 @@ user ---- id +auto_renew, Boolean +current_product, enum(ABO, BENEFACTOR_ABO, MONTHLY_ABO, ABO_GIVE_MONTHS) + subscription credit ------------------- From 8174fb223915f405cf3fbe232f051a4f8d71b3b5 Mon Sep 17 00:00:00 2001 From: Pierre Spring Date: Mon, 10 Aug 2020 18:06:44 +0200 Subject: [PATCH 3/5] fix typo --- concept/membership-v2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concept/membership-v2.md b/concept/membership-v2.md index 19ddb84..cd0faa1 100644 --- a/concept/membership-v2.md +++ b/concept/membership-v2.md @@ -22,7 +22,7 @@ debit createdAt Date endedAt NULL | Date -CONSTRAINT "only one active subscription" UNIQUE(user.id, endedAt) +CONSTRAINT "only one active debit per user" UNIQUE(user.id, endedAt) payment history --------------- From f39c7a8e4dc9b6bc2bc9d7acbcb64122fa963d45 Mon Sep 17 00:00:00 2001 From: Pierre Spring Date: Mon, 10 Aug 2020 18:19:00 +0200 Subject: [PATCH 4/5] better layout --- concept/membership-v2.md | 57 ++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/concept/membership-v2.md b/concept/membership-v2.md index cd0faa1..843277e 100644 --- a/concept/membership-v2.md +++ b/concept/membership-v2.md @@ -1,35 +1,42 @@ # Membership V2 -```md -user ----- -id -auto_renew, Boolean -current_product, enum(ABO, BENEFACTOR_ABO, MONTHLY_ABO, ABO_GIVE_MONTHS) +## Tables +### user -subscription credit -------------------- -id -user_id -credit, INT, Amount of days -createdAt +| Field | | +| --- | --- | +| **`id`** | | +| **`auto_renew`** | Boolean | +| **`current_product`** | enum(ABO, BENEFACTOR_ABO, MONTHLY_ABO, ABO_GIVE_MONTHS) | -subscription debit ------------------- -user_id -debit -createdAt Date -endedAt NULL | Date +### subscription credit -CONSTRAINT "only one active debit per user" UNIQUE(user.id, endedAt) +| Field | | +| --- | --- | +| **`id`** | | +| **`user_id`** | | +| **`credit`** | INT, Amount of days | +| **`createdAt`** | Date | -payment history ---------------- -price -product, enum(ABO, BENEFACTOR_ABO, MONTHLY_ABO, ABO_GIVE_MONTHS) -subscription.id -``` +### subscription debit + +| Field | | +| --- | --- | +| **`user_id`** | | +| **`debit`** | | +| **`createdAt`** | Date | +| **`endedAt`** | NULL | Date | + +`CONSTRAINT "only one active debit per user" UNIQUE(user.id, endedAt)` + +### payment history + +| Field | | +| --- | --- | +| **`price`** | | +| **`product`** | enum(ABO, BENEFACTOR_ABO, MONTHLY_ABO, ABO_GIVE_MONTHS) | +| **`subscription`.id** | | ## Queries From 67408d2c83aaa8f144f2c625bcb645cfd6ddb103 Mon Sep 17 00:00:00 2001 From: Pierre Spring Date: Wed, 12 Aug 2020 12:28:37 +0200 Subject: [PATCH 5/5] add membership state machine --- guides/membership-state-machine.ts | 71 ++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 guides/membership-state-machine.ts diff --git a/guides/membership-state-machine.ts b/guides/membership-state-machine.ts new file mode 100644 index 0000000..08d3e6e --- /dev/null +++ b/guides/membership-state-machine.ts @@ -0,0 +1,71 @@ +type StateName = + | 'lead' + | 'prospect' + | 'trial active' + | 'trial active, yearly dromant' + | 'yearly active' + | 'yearly grace period' + | 'yearly active, yearly dormant' + | 'monthly active' + | 'monthly grace period' +// | 'monthly gift active' + +type Trigger = + | 'activate free trial' + | 'buy yearly' + | 'buy monthly' + | 'buy prolongation' + | 'redeem monthly gift' + | 'prolongation auto-payed' + | 'active period ends' + | 'grace period ends' + +type State = { + [key in Trigger]?: StateName +} + +type States = { + [key in StateName]: State +} + +const states: States = { + lead: { + 'buy yearly': 'yearly active', + 'buy monthly': 'monthly active', + 'activate free trial': 'trial active' + }, + prospect: { + 'buy yearly': 'yearly active', + 'buy monthly': 'monthly active' + }, + 'trial active': { + 'buy yearly': 'trial active, yearly dromant', + 'active period ends': 'prospect' + }, + 'trial active, yearly dromant': { + 'active period ends': 'yearly active' + }, + 'yearly active': { + 'active period ends': 'yearly grace period', + 'buy prolongation': 'yearly active', + 'buy yearly': 'yearly active, yearly dormant' + // 'redeem monthly gift' + }, + 'yearly active, yearly dormant': { + 'active period ends': 'yearly active' + }, + 'yearly grace period': { + 'buy prolongation': 'yearly active', + 'prolongation auto-payed': 'yearly active', + 'buy yearly': 'yearly active, yearly dormant', + 'grace period ends': 'prospect' + }, + 'monthly active': { + 'active period ends': 'monthly grace period', + 'prolongation auto-payed': 'monthly active' + }, + 'monthly grace period': { + 'prolongation auto-payed': 'monthly active', + 'grace period ends': 'prospect' + } +}