Search code examples
design-patternsdatabase-designsubscriptionsubscriptions

Strategy for keeping track of a user's tokens/coins


I'm working on a web app where users buy tokens/coins on a per month basis - meaning tokens expire at the end of the month (e.g. $3 will get you 5 tokens for the duration of a month). I am a bit confused as to what strategy to take when it comes to storing and keeping track of each users tokens.

In a two part question:

1) Since a user can typically buy tokens during any stage of the month, are months defined as "30" days, or do they map to the days of a calendar Month? (example: if tokens are bought during March, would they last 31 days, but if bought in May they last 30 days?)

2) The second part of the question is how do I track these tokens? If a user pays for a year long subscription (5 tokens every month for 12 months) but is also allowed to buy more tokens during the course of the year (for June user wants 10 tokens), how can I actually keep track of how many tokens have been bought for each month?

I have a few implementation ideas in mind, but none of them seem 'right'. Was hoping someone may have tackled a similar problem or could point me to any relevant literature.

Thanks in advance.


Solution

  • Since a user can typically buy tokens during any stage of the month, are months defined as "30" days, or do they map to the days of a calendar Month? (example: if tokens are bought during March, would they last 31 days, but if bought in May they last 30 days?)

    Always 1 full month.

    Why? because you are nice to your users ;)

    I would choose a full month because of the simplicity in date methods. And easier to keep track for members. 31 days is a better option for people who like to buy the most tokens at the end of february. For example a purchase on January the 31th will be expired on March the 3rd in stead of february the 28th.

    Of course you can decide for yourself, but this is the most reasonable option which also ensures you get less trouble with customers.

    The second part of the question is how do I track these tokens? If a user pays for a year long subscription (5 tokens every month for 12 months) but is also allowed to buy more tokens during the course of the year (for June user wants 10 tokens), how can I actually keep track of how many tokens have been bought for each month?

    Create a table for each token purchase with the time and date of purchase and the amount of tokens.

    TokenPurchaseNumber | UserId | TokenCount | PurchaseDateTime| ExpireDateTime
    ---------------------------------------------------------------------
    10001               | 1      | 200        | Jan 20          | Feb 20
    10002               | 1      | 100        | Jan 24          | Feb 24
    10002               | 2      | 300        | Jan 24          | Feb 24
    10003               | 1      | 20         | Jan 25          | Feb 25
    10004               | 1      | 40         | Jan 29          | Feb 29
    

    This way you have a good archive of all purchases with a unique purchasing number, and you can generate purchase history for users.

    You could consider not using the ExpireDateTime column because you just compare the date of tokens bought + 31 days with today.

    Now how do you calculate the total of tokens a user has seems to be the next question.

    Two options, the first will have a better purchasing history and archive.

    Option 1:

    This is fairly easy, every time a user purchases tokens you create a row in the above table but also adds it up to his total amount saved in his own user table column tokens.

    Every time a user logs in (or any other chosen time you want), you can check their total tokens for example 165.

    Now today is the 21th of February, so you check all his token purchases after January the 21th. We add those up and we see the user can only have a possible amount of valid tokens of 100+20+40=160. So we remove 5 of his tokens and send him a message, 5 tokens of his #10001 purchase on Jan 20th are expired.

    Second option:

    Just remove tokens from the oldest purchase when a user use them. When the expiration date has expired, remove the entire purchasing row, effectively removing the remaining tokens of that purchase.