October 7, 2004

Financial Transactions

I've been working on an electronic commerce site for work now for the better part of a year. You would be amazed at the amount of complexity that goes on under the covers.

Let's take two features and dissect them: discount rates and convenience fees. These two features are intertwined in the most interesting ways.

To each transaction (meaning group of line items paid for at once), we add a convenience fee. So, you may register five kids for soccer and pay your water bill all at the same time, but we only charge a single convenience fee for all of this.

When we send the charge to the payment gateway, a percentage of that is removed from the total you receive. So, if you had a discount rate of 1%, you would get $99 of a $100 purchase.

First thought: Remove the entire discount from the convenience fee. That's the easiest way to handle this, right? It's the easiest. It's also illegal. It is against the law to charge extra to someone who wants to use a credit or debit card to purchase something. You can give people who pay cash a discount, but you cannot charge others extra. By using the convenience fee as the sole buffer, you're essentially creating a fee just for them.

Second thought: Figure out what percentage the discount is, and remove that percentage from each line item. That's legal and mathematically sound, but for accounting purposes, each line item must not have a fractional penny. How should you deposit $1.113? Does that $0.003 vanish or what? The rules of government accounting actually do account for this in an effort to stop "Superman 3" or "Office Space" style skimming.

Third thought: Take the discounted amount and put it into a temporary variable. Figure out the percentage that the discount rate is of the gross, and put that into a temporary variable. Take that percentage of each line item except the last one, and use a Math.Floor(amount*100)/100 to get the line net. Subtract the line net from the temp variable storing the discounted amount. On the last line item, take away the remainder. That works, but has problems if you try to reverse the process.

Final thought, and what we have implemented: Store the sign of the base amount. Run the above on Math.Abs(amount). Restore the sign. All done.

I realize that this seems like it's being overanalyzed, but government financial transactions have very specific requirements. If I don't follow those requirements to a T, at the very least I'm putting the city at risk. At the very most, I'm violating city, county and state laws.

All I'm saying is that you should be very careful about shortcuts you would normally take when you are dealing with money. I've had to write our own in-house because all of the electronic commerce suites that we tested wouldn't pass our audit tests. Would yours?

No comments: