September 22nd, 2010, 04:00 PM
My first exception design
I'm working on a piece of software that can be described no better than with the hyphenation: Spaghetti-code.
This problem seems to stem from one blatant fact. When they designed this, the only documentation they have is user stories and an end user manual that is outdated and incorrect.
What I am doing right now is working on a bug that I have reviewed before and spent almost 3 months writing a script to fix the data. Now it's time to correct the bug. The bug is fairly simple to explain. Given an average cost inventory system, if your average cost has to be rounded your general ledger(Accounting) will go out every time you sell the item.
There are two problems I see to this:
1) The original developers didn't check and make sure that the average cost multiplied by the inventory count adds up to the actual amount that went into the inventory account.
2) The second problem I see is that they calculate the average cost in the class that is making the change for the average cost. For example the sales class doesn't use the same code as the purchasing class. They both instead use a different control structure on what seems to be almost the identical code with minor changes for the specific scenarios.
My solution to these two problems is simple:
1) Write an exception to throw when the rounded average cost doesn't equal the raw 2+ decimal average cost.
2)Write a 'static' function that recalculates average cost based on an inventory adjustment(part number, quantity, price per/global amount and some flags) rather than in a linear format in the class you're trying to change the average cost from.
Now, I don't have much design experience, none formally. My thoughts around this are as follows:
Every time an average cost calculation is going on, instead call the static function. Within this function I want to check the rounded average cost against the raw calculated average cost. If they don't equal, this means that their GL account will go out. At this point I want to throw an 'AverageCostException'.
This exception, which I have never used before aside from pre-defined exceptions, will take the adjustment and figure out what values closest to the ones provided it can use to get an average cost to even out to the penny. The average cost could then return these numbers and they can be used in a catch, in the native class code, to display a special window that will let them pick either a different adjusting cost or cancel the transaction. There is a scenario that will make having a non-even average cost a legitimate thing. This would be a purchase. IE you have 57 of one part at 1.50 and you buy 69 more at 1.41. The average cost is 1.450714, rounded to 1.45. Every time they sell this item, their inventory account would be inflated by 0.0714 cents. This doesn't sound like a lot but if the store is big enough, this can throw the account out quite a bit. Accountants accept this but for the most part, accountants aren't looking at the reports, they are providing them. So if the reports don't add up we get complaints. So the solution I had was to move the amount per item(0.0714) and add a line for every quantity able to be sold and as the item is sold delete one of these lines and add up the lines to get an actual total for their GL.
The reason these amounts can't go into the current system is that the current database only stores up to 2 decimal places. A proper solution would probably allow dollar figures to allow for 6 decimal places.
My actual question is:
where should I do the calculating as to what other options someone has once it has been determined that their average cost is being rounded to throw off their GL Inventory account. My thought is in the exception class I defined to catch this type of scenario. Any other option seems to involve either too much copy and paste or I don't see it. Any comments and suggestions welcome.
September 24th, 2010, 03:07 PM
So I've come to the conclusion that the exception should handle the inconsistencies of normal execution. My plan is to multiply the adjustment by the fractions of pennies lost which will give me a whole number, to the penny, and put that in a variance account to be used in reporting and balancing.
September 6th, 2011, 11:13 PM