Designing a system for handling in-application economy using currency or credits - ruby-on-rails

I'm currently developing an application where I need to implement some sort of way of handling credits which are purchased by users of my application. These credits will then be used to preform certain tasks inside my application such as purchasing hits in mechanical turk. The reason I need to do this is because in the case of mechanical turk there is a possibility that our orders won't be filled and instead of just keeping the extra money for hits they didn't get I want to credit them for future purchases.
The important parts I need help fleshing out is how do you accurately manage an ongoing total of credits. I can't obviously calculate it every time. Additionally I need to manage the adding and subtracting of the credits. Also I probably need to track the origin of these credits, ie money or free because it is possible we might give out free credits as a reward but we need to be careful how to handle turning free credits into cash because it opens an incentive for scammers to use the credits to purchase turk hits then do the turk hit themselves and keep the money.

I currently work on a system with something very similar.
Users have an Account which tracks all transactions - origin, type and amount. We have a finite number of transactions types (including obvious the ones like credit/debit). The Account table is therefore actually an archive of all of the transactions for a particular user account, rather than being a simple running total.
Account totals are therefore calculated every time we need them, although it would be pretty simple to add some aggregates to the database that increment/decrement a total value as transactions are processed. As with all performance-related issues - don't do it until you need to, summing values across some smartly indexed columns is fine for our current system.

Related

Shopify API Customers orders_count Rails

I'm in the process of making an app that will update shipping depending on what your order_count is using ShopifyAPI::Customer.
One main thing I'm trying to accomplish is being able to reset the order_count to zero for all customers.
I have been trying:
order = ShopifyAPI::Customer.all
order.update_all(:orders_count, "0")
It works when I'm addressing a single customer, but not Customer.all. Is there a way I can work around this to update all customers in the db at once?
Can you actually change a valid orders_count? It would be pretty crazy in my mind if Shopify allowed that.
If I were you, and I am not, for sure, I would simply change my algorithm so that it is more of a "How many orders has this customer placed since last tuesday?". That way, I reward them if their purchases exceed that threshold of X.
In your case, you are trying to erase their legitimate order history to make your counter work, which I doubt works.
In the meantime, if you can indeed set that count to zero, just loop through all the customers, and for each one, save their count as zero. There is no one shot all customers call in Shopify API, just like there is no one shot anything. Every resource is a one-off.

calculating lots of statistics on database user data: optimizing performance

I have the following situation (in Rails 3): my table contains financial transactions for each user (users can buy and sell products). Since lots of such transactions occur I present statistics related to the current user on the website, e.g. current balance, overall profit, how many products sold/bought overall, averages, etc. (the same also on a per month/per year basis instead of overall). Parts of this information is displayed to the user on many forms/pages so that the user can always see his current account information (different bits of statistics is displayed on different pages though).
My question is: how can I optimize database performance (and is it worth it)? Surely, if the user is just browsing, there is no need to re-calculate all of the values every time a new page is loaded unless a change to the underlying database has been made?
My first solution would be to store these statistics in their own table and update them once a financial transaction has been added/edited (in Rails maybe using :after_update ?). Taking this further, if, for example, a new transaction has been made, then I can just modify the average instead of re-calculating the whole thing.
My second idea would be to use some kind of caching (if this is possible?), or to store these values in the session object.
Which one is the preferred/recommended way, or is all of this a waste of time as the current largest number of financial transactions is in the range of 7000-9000?
You probably want to investigate summary tables, also known as materialized views.
This link may be helpful:
http://wiki.postgresql.org/wiki/Materialized_Views

difficult architectural problem involving recurring payments and future events

I'm looking for guidance on how to architect an elegant solution to what has become a bit of a thorny problem. Although I am using Ruby (and Rails) I think my problem is largely an architectural one, though my choice of language obviously has an impact in terms of suggestions involving libraries, etc., so the language remains relevant.
Anyway, in a nutshell: my application contains objects representing memberships, belonging to people who are members of fitness facilities. Memberships contain a series of recurring payments. Some memberships automatically renew at the end of their term, while others do not.
So for example, you may have a membership that is for an initial period of one year, and then renews month-to-month after that. In the application, creating a membership of this kind causes 12 recurring payments to be created. When the last month expires, so does the membership. A daily cron task is responsible for causing memberships to expire based on completed payments. If the membership is set to automatically renew, the same cron task will renew the membership.
You may also have memberships that have no initial term and simply run month-to-month or week-to-week. These work in a similar manner, minus the initial payment scheduling.
So far so good. What makes things complicated are the additional requirements:
administrators can "freeze" memberships (put them on hold), for specific durations, after which they automatically reactivate (e.g. to represent people who go away on vacation for a set period of time). I can choose to freeze a membership right now and have it reactivate later, or I can choose to schedule a freeze by setting the freeze date at some point in the future, as well as the reactivation date (note: there is always a reactivation date, which makes things a bit easier).
administrators can cancel memberships, either right now, or by setting a cancellation to occur in the future. (Future cancellations are not yet built.)
administrators can refund memberships, which is like a cancellation except any past payments are refunded.
What makes these difficult to deal with is the effect on recurring payments. When you freeze a membership, the recurring payments must "stretch out" around the freeze period, so that the period of time that represents the freeze is not paid for. This is both conceptually and programmatically difficult to handle. Payments, for example, may extend for different periods (i.e. each payment for someone who pays every other week pays for two weeks of a membership), and the date of cancellation may be anywhere within the period the payment covers.
For the freezes, I have taken the approach where the membership object contains some dates, namely "freeze_on" and "thaw_on" to handle the freeze period. However, the client now wants future cancellations as well, and I have noticed some bugs with the freezing functionality, which leads me to believe I need to reconsider my approach.
I am considering changing things so that future events can be scheduled but have no effect on the recurring payments portion of the application. The idea would be to queue up particular events. For example, a freeze in the future would be accomplished by queuing up a freeze event on a particular date, and a thaw event on a subsequent date (these two events would be connected into a single "scheduled freeze" from the user's perspective). A future cancellation would be handled similarly.
This approach has some benefits, for example, if you wanted to cancel a future cancellation (that's the kind of annoying, tricky stuff I'm talking about), you could simply remove the scheduled cancellation from the events queue.
However, I have the nagging feeling that I may simply be jumping from the frying pan into the fire. I'm wondering if anyone could provide me with some guidance on this issue. Are there design patterns or existing architectural principles for this sort of problem that I can examine?
An additional thing to note is that recurring payments for memberships with scheduled terms (i.e. not month-to-month automatically renewing) must exist as database records that can be edited (moved in time, price adjusted), so using temporal expressions (as Martin Fowler suggests) is not appropriate for this problem, so far as I know. I realize that my proposed solution of an events queue would not display to the user the changes that would happen to any existing recurring payments, but I think I can live with that.
not a scanlife bar code, it's a qr code
toronto, give us your creative people
Edit: To respond to the two great suggestions below (the comment boxes don't allow nearly this level of detail):
Kris Robison:
Yes, the freeze period can be an arbitrary length, although in practice I imagine it would be rare for it to be less than two weeks. But any solution should work regardless of the length of the period.
Yes, the renewal date changes - it is pushed forward by the length of the freeze. So if the freeze is two weeks long, it pushes the payment forward by two weeks. To make things especially tricky, in some businesses, the payments can only be withdrawn on specific dates - for example, some clubs only process payments on the 1st and 15th of each month. So when dates are pushed around, for these clubs, they have to "snap" to a particular date.
Can you explain in more detail why these rules affect event queuing but not management of subscription payments?
I'm interested in your amortization table concept. That's basically exactly what I have built already - a year-long membership with monthly payments creates 12, with weekly it created 52 - and each of these have an amount, tax, etc., associated with them, along with a state machine that governs "pending", "paid", "failed", and "refunded" states.
The part I am struggling with is how this table responds to events. Right now, if you set a freeze, it affects the table immediately by changing the dates of the payments. Set a freeze in the middle of the table, and it pushes payments forward. That sounds effective, but it's actually quite complex and hard to manage. How would your amortization table idea improve this situation?
Arsen7:
This sounds like the event queue I proposed originally. It seems obvious to me that you've worked with stuff like this before (I was impressed by your error check on the processing date, this is a great idea and one I intend to implement ASAP) so I'm hoping that you can explain your suggestion in a little more detail.
Specifically, I'm wondering how your concept would deal with the recurring payment situation I've described in my original question, and in the comment that I just left on Kris Robison's answer. If I have set up a schedule of recurring payments for a given purchase, and a freeze event is scheduled for right in the middle of the payments, would the schedule of payments remain unchanged until the date of the freeze became the current date, at which time the freeze would be instituted and the payments would move forward?
This strikes me as perhaps a great way to simplify my application, but I am wondering how users would perceive it. How would I indicate to them that the schedule of payments they were looking at when a freeze has been scheduled is no longer an accurate schedule, but will change once the freeze takes place?
Is it acceptable to apply a scheme used by banking, where you process all account operations once a day?
Every object may have a set of (future) operations, like freeze periods, and every day the object has to make a simple decision, like: "should I expire today or not?"
The good part is, that such daily processing is very simple to program. Also a strange renewal rules (in case you would want them) are simple to design: "is it Friday? is it the last one in this month? If yes, mark me as renewed, add some amount to required payment, or do anything".
That would be very costly (in terms of computing power) to calculate the status dynamically, every time the object is asked. If you store the current "account", you only need more complex calculations when you want to predict future state.
Consider it a pseudo-code:
def process(day)
raise "Already processed or missed a day" unless day == last_processed_day + 1
check_expiration day
check_frozen day
check_anything day
#...
self.last_processed_day = day
self.save!
end
RESPONSE:
Specifically, I'm wondering how your concept would deal with the recurring payment situation I've described in my original question, and in the comment that I just left on Kris Robison's answer. If I have set up a schedule of recurring payments for a given purchase, and a freeze event is scheduled for right in the middle of the payments, would the schedule of payments remain unchanged until the date of the freeze became the current date, at which time the freeze would be instituted and the payments would move forward?
This strikes me as perhaps a great way to simplify my application, but I am wondering how users would perceive it. How would I indicate to them that the schedule of payments they were looking at when a freeze has been scheduled is no longer an accurate schedule, but will change once the freeze takes place?
The "daily processing" scheme helps you with providing quick responses for questions which require complex calculations.
You have three "groups": current state (asked often), history (almost never changing, asked relatively rarely), and future.
Your daily processing procedure is not constrained to only update "current" state. If some event is scheduled for the processed day, the procedure probably needs to add "history" records.
If your users will often ask questions about future (and as you said, they will), the "processing" may also create a kind of cache for these questions. For example: find (calculate) the next payment date, and write it in a helper table (a schedule).
The main thing you need to do is to decide which questions will be asked by users, and whether you are able to calculate the responses on-the-fly or you need to have the answer prepared.
In a bank (it varies, of course) if you ask about your current balance, they may give you the answer which was true at the beginning of the day. "Better" banks will tell you that you had X$ at the morning, but now there are also Y$ waiting for accounting.
So, if you put a freeze record into the event queue, you may call a method, which will update the schedule at once. The same procedure (or a very similar) will or may be called in the daily processing routine.
Couple of questions come to mind:
Can the freeze be for time periods less than a month?
If so, does the renewal date change? Or how does the monthly payment get applied for the partial month?
Those affect how your event queuing system may work, but don't ultimately change the management of subscription payments.
One way to address subscription issues is to create an amortization table of subscription payments. If they are paying monthly for a year, twelve payments are queued up in the table. A weekly customer may have 52 payments in the table for the same year. Each time the renewal date comes up, after checking whether a freeze is in place, apply the next payment.
The amortization table keeps track of which payments have been made. If an account cancels, unpaid rows are refunded. If an account freezes according to your event queue, no payment is applied and the table remains static until the account is thawed.
Reply
It sounds like you have the concept of renewal date built into the amortization table. I use the amortization table more as a queue, and keep just the next renewal date with the subscription.
If the renewal date is inherent with the amortization table, then yes, it would be complicated to make changes as things go along. However, the renewal date should only affect the day on which you check to see if another payment gets applied.
If you are preserving partial payments while a subscription is on hold, and if a hold can be for an unspecified period of time, having the duration value on the amortization table lets you push a partial payment back in the queue in a "credit" state with a duration equal to the remaining time left in the payment. That way when the account is thawed, that partial credit is applied first and you calculate the next renewal date from the remaining duration.
Use some form of ordered list to preserve payment order at this point. It also comes in handy should someone ever want to insert a renewal period's worth of credit for customer service reasons.

Gift Card/Debit Card Activation

General Problem
How do retail establishments constrain activation for gift cards, or those pre-paid phone/debit cards?
They must have a system in place that only keeps you from calling in to activate cards that haven't scanned through the register, and I assume there must be a standard solution built into the retail ERP/accounting systems. It probably involves web services or EDI.
Specific Problem
I ask all this because one of my clients wants me to develop a product that you get into by purchasing a $30 card at a retail store. The card has a unique number on it. Once you've purchased a card and activated it via a web site, coupons for restaurants and so on are emailed to you periodically.
However, if someone were to steal a bunch of cards or figure out the numbering sequence, we don't want the cards to work.
Presumably, this is a solved problem because retailers are doing this with the products above (pre-paid phone cards, etc).
I can think of a number of ways to solve this problem, however I need to provide the "standard" solution that the retailers expect, so that the product will snap into their infrastructure in the normal way.
Thanks a lot!
I've worked on a few of these types of systems and they all basically work the same way. The card has a # encoded into the magnetic strip (it could also be a barcode). That's usually all that's on the card itself. Cards are then activated at time of purchase.
Here's the basic flow:
Customer comes in and purchases a card:
The card is swiped and/or scanned.
A call is made to an on-line system (usually via some type of webservice call). It includes the card #, the amount they are activating with, and maybe a bit of additional information (ex. invoice #), and possible something like the previous transaction #.
If the call is successful, you get back a transaction ID #.
If the call fails, there is usually some protocol you are supposed to follow (sometimes handled during the daily settlement process). Things like retrying the activation, or running a query to determine if the last transaction went through.
If it was successful, the card is now active.
So basically, the card is worthless until it's activated. At that point it becomes "live" and has money associated with it. That is, back on some server somewhere is a database that has this card #, when/where it was activated, amounts, etc.
There is usually some functionality to generate an "end of day" transaction report to help you reconcile your numbers (what your system says vs what they have recorded).
Since cards are centrally managed it becomes easy for them to flag cards if they were stolen (not that it matters since they have $0 value until they have been activated).
I found out through other sources that there are about eight card processing services that integrate with the various retail locations.
Each retail location uses one. When a card scans through the register, the retailer notifies the card processing service (unlocking the PIN so that it can be activated), and then presumably the card processing service notifies us via an API call.
Then, when the customer goes to activate their card, we can tell which ones have scanned through the register (because they are unlocked). In this way, we get around problems surrounding stolen cards or guessed pin numbers.
The names of a few of these networks are:
Blackhawk Networks
InCom
Coin Star
I had the joy of working on one of these systems right out of college. Depending on the way they handle their processing whether end of day batch or weekly report could cause quite a lot of problems. One of the things I saw was that if the person whom had the card, whether legit or not, if they managed to make a bunch of purchases that were < the day's starting balance but by the end of the day > greater than starting balance all the purchases would go through. Not very fun when the company had to swallow upwards of 100 dollars per user a day.
In terms of security, make the company that you interface with be held responsible for purchases. That is the best way of handling this in what I have seen, because that is what they are there for. Hope that helps in some roundabout way.
You have to be careful, I have seen this played out in retailers..a customer in front of you is asked if they have a loyalty card by the cashier. The customer says no, but the customer behind them offers their card and it gets swiped hence collecting points for something that they did not buy...
Thus gets points at the expense of the customer in not having it thus skewing/distorting the results of the customer (the one who has a loyalty card)'s personal shopping experience and what they did not buy...on the appropriate system's database
In short, there is no foolproof way of getting around that other than asking for a retina scan or finger print that identifies the customer. Some customers would be cautious in joining a club in regards to their privacy...that is another thing to be kept in mind...not all of them would have a loyalty card...
Hope this helps,
Best regards,
Tom.
I believe that the most secure solution possible is to have a server that generates and prints (or exports) the card numbers. When a customer is interested in purchasing a gift card, it is scanned at the register and the register notifies the server that the card has been approved (probably with the credentials of the cashier).
Then when input on your website, the website checks with the card server to see if the card number is valid and approved.
Then, stolen cards are not approved. If someone figures out the numbering scheme, then you may be screwed so it is recommended that the numbers be random with enough digits to make guessing numbers unreasonable (perhaps with something similar to a CV2 code).
This is similar to how debit cards work: card number/CV2 generated ("server") -> shipped to customer -> customer activates via phone ("register", with the "credentials" being their SSN or similar) -> customer then uses at a store and the store contacts the card company's server
I know that Intuit Quickbooks Point of Sale offers a service like this (complete with an API), you could look them up.
I like HalfBrain's solution. I'd also imagine they have certain pieces of security in mind, like a single IP address (or some other criterion) with more than some number of failed activation attempts getting flagged for apparently attempting to probe the system.

Anyone got a nifty credit expiry algorithm?

Our website uses a credit system to allow users to purchase inexpensive digital goods (eg. photos). We use credits, rather than asking the user to pay for items individually, because the items are cheap and we are trying to keep our credit-card/PayPal overhead low.
Because we aren't a bank, we have to expire credits after a certain amount of time. We expire deposit credits after a year, but other types of credits (bonuses, prizes, refunds) may have a different shelf-life. When a buyer buys an item, we spend the credit that is going to expire first.
Our current system keeps track of every deposit by storing the original value and the remainder to be spent. We keep a list of all purchases as well, of course.
I am currently moving to a system which is much more like a traditional double-entry accounting system. A deposit will create a ledger item, increasing the user's 'spending' account balance. Every purchase will also create a ledger item, decreasing the user's 'spending' account balance. The new system has running balances, while the old system does not, which greatly improves our ability to find problems and do reconciliations.
We do not want to use the old system of keeping a 'remainder' value attached to each deposit record because it is inefficient to replay a user's activities to calculate what the remainder of each deposit is over time (for the user's statement).
So, after all of this verbose introduction, my question is "Does anyone else out there have a similar system of expiring credits?" If you could describe how you calculate expired credits it would be a great help.
If all expired credits had the exact same shelf life, we would be able to calculate the expired amount using:
Total Deposits - Total Spending - Deposits Not Due To Expire = Amount to Expire
However, because deposits can have different shelf lives, this formula does not work because more than one deposit can be partially spent at any given time.
No, I don't have a similar system, but it sounds like you should probably add the expired credits to the ledger as debits.
These credits you describe don't sound to me like a currency; they sound more like a financial instrument with an expiration date, like an option or a futures contract. If you use conventional double-entry bookeeping, and account for each instrument individually the same way a financial brokerage would, then things should work out about right.

Resources