Stock levels in DB

P00HB33R

Senior Member
Joined
Jul 15, 2010
Messages
708
Reaction score
29
Location
Eloff
What is the best strategy to keep stock levels in a database?

For argument sake, I have a Invoice Table and a Item Table.

Here are my strategies i have come up with so far:

1. Subtract the QTY of the item in the invoice from Item Tables "QTY ON HAND" field on every transaction (eg new invoice)
* Add QTY back to QTY ON HAND in case of return/credit note

2. Calculate QTY ON HAND each time a item stock check is requested, or in case of QTY not allowed to go into negative, everytime a item is added to invoice line.

Any other suggestions, or which one of 1 or 2 is the best?

Any feedback/suggestions will be much appreciated.
 
Depending on size of business, you may also want to think about Allocating items that are in picking process (and generate pick list). This means you will also have to calculate Available. Also think about incoming stuff - i.e. On Order, In Transit from another branch, etc
 
That I will do. But for now I am more concerned with the best strategy to follow, as it would apply to all stock level maintenance.
 
I can make quite a few suggestions to give you ideas. I wrote a whole ERP system for a niche industry. Stock holding , invoices purchases was core of this. Are the items serialized i.e. individually unique or not? Makes a big diff...
 
@spacerat: Products will be not be serialized. So I just need to keep track of lets say ProductA, ProductB, and ProductC.

If they were to be serialized, what is the best strategy, for interest sake? (Correct me if Im wrong but by serialized you mean that each item is tracked individually and not as a collection of ProductA?)
 
Something to take into consideration is warehouse locations. You might not need it now but maybe in the future ?
What about stock value or is QTY more important ?

Invoice Table
Item Master Table
Location table.

Our ERP (Sage 300, AKA accpac) keeps info the following tables.

OEINVH Invoice Header
OEINVD Invoice Detail

OECRDH Creditnote Header
OECRDD Creditnote Detail

ICITEM - Item Master
Item Number
Description
Category
Whole bunch of other stuff.....

ICILOC - Location Details.
Item Number
Location
Bin Number
QTY On hand (Calculated value on each transaction)
QTY On order (Calculated value on each transaction)
QTY On Sales Order (Calculated value on each transaction)
Last cost (Calculated value on each transaction)
Average cost (Calculated value on each transaction)
ect ect ...

And then maybe a bit over the top for what you want to do but will it certainly put your stock maintenance under control and give a clear picture in case you need to investigate.

ICHIST - a Log of ALL stock related transactions. Credit notes, Purchase orders, Invoices, stock Adjustments, Stock Transfers (One location to another)
DOCUMENT NUMBER
ITEMNUMBER
TRANSACTION Amount
Transaction QTY
Location
Date
ect ect
 
Last edited:
SBSP has some good suggestions. Also, tracking value is different from tracking qty. Value can be based on Avg costing or FIFO. Very different implementations.

A lot of the implementation deoends on your requirements. Firstly, lets assume you track 'qty of' like items Product A/B/C as you said. So typically you will have a table that identifies the product code with a unique code, some descriptions etc and Current stock qty. I normally like to have a top-level qty that shows the total qty of items in stock:
Table PRODUCT
- CODE
- NAME
- QTY

There are several activities that influence product qty:
- Receipt
- Sales/Invoice
- Stock adjustment during stock count
- transfers from one location to another. This does not change total stock, but changes stock qty in the diff locations.
- etc

What i like to do is to create an audit or detail table that records each and every qty change in the system. not only is that good from an audit perspective, but also good from a support and reporting perspective. I.e. looking at a single product code, be able to see all the changes in qty for that product code by looking in one place. By tallying the audit records, the top level total as well as the receipts and invoices and adjustments in a 3-way comparison you quickly find bugs. So the audit table could look like this

-ID
-Timestamp
-UserId
-ProductCodeId
-TransactionTypeId
-Qty
-ReceiptId
-InvoiceId
-FromLocationId
-ToLocationId

Each and every update to qty has one or more entries into this table as well as the ProductCode table qty.

The timestamp and user columns could tell you who made the change and when. The TransactionTypeId identifies the activity that caused the qty change e.g. Receipt, Sale, Transfer, Stock Adjustment, etc. Then in the audit table you can also store a reference to the document that relates to the change. What is important is that the Qty column is >0 for increases in qty and <0 for decreases. This means that ProductCode.Qty = sum(Audit.Qty). Believe me you gonna need this and at some point and your customer will ask for this.

One of your questions related to whether you calculate then qty on the fly or not. Always keep a total qty. You cannot, as the system grows, total up millions of rows just to get the current qty. If you suspect the top level qty is wrong you can always reupdate it from the audit (after you fixed the bug that cause it to drift). Having th qty on the ProductCode row also makes coding so much easier. You have to obviously be aware of concurrent updates and how to resolve those conflicts but we can dwell on that later if you wish.

When it comes to updating qty and inserting an audit record, it depends on your requirements and intended workflow. In my case, you could create a sale and add products to a sale. This does not yet update qty because you can cancel a sale. Only when you invoice the sale, you update qty because you can never cancel or delete an invoice. The invoice activity is a point of no return. The only way to reverse an invoice is to issue a credit note. That in turn increases stock again.

These were just some initial thoughts, sitting in bed. Feel free to ask if you have detailed questions.

EDIT: as a matter of interest, my ERP manages stock as above (I call it non-tracked items) as well as tracked items where each item has its own life-cycle throughout the production (receipt to sales). The individually tracked items build up a complete history of attributes as it moves along the production process. The implementation is totally different from normal stock management because of the traceability aspect.
 
Last edited:
A criptic overview.
I would recommend one set of files (header and item) for both inv and cn.
Also order head and item
stock transaction file - by whouse / article. Make provision for digital recon of stock transactions and cross reference and inv to job etc.
Do track item ID in this file. Use job item or grn item file.
stock master
stock location master - stock balances, on order, reserved, min , max, reorder qty, reorder point, etc.
job master and job item :
selling prices

I would not recommend blocking negative stock balances as this means that you force the order in which data processing takes place.
As if goods are received they must be GRN'ed before customer can be supplied.

Hope you follow my train of thought.
 
Please do not use a 'database' that is file per table. That is antiquated. Use a modern RDBMS.

A criptic overview.
I would recommend one set of files (header and item) for both inv and cn.
Also order head and item

Personally I prefer to keep all entities in separate tables. i.e. INVOICE, INVOICE_LINE, CREDIT_NOTE, CREDIT_NOTE_LINE. I dont like to 'pollute' an entity with data from another type of entity.

I would not recommend blocking negative stock balances as this means that you force the order in which data processing takes place.
As if goods are received they must be GRN'ed before customer can be supplied.

Data processing should not be batch in background. It should be realtime. That means that transactions will be usually executed in correct time order. Selling and invoicing goods normally happens some time after receipt. Except though in FMCG scenarios where you have cross-docking. The main reason where negative stock comes into play is where the theoretical stock qty and physical stock qty has drifted. I.e. theoretical says Qty=0, but you have actual physical stock. To sell that item means that theoretical will become < 0. In this case you'd want someone to know about this in order to do a stock check on that item...
But I would add a flag to the ProductCode table so that you can config the ability to go negative on a per Product Code basis.
 
As for point 1; it's a bit more complex than that; consider that the cost of the item will vary over time i.e. for your returns what book value will you'll use for the credit (e.g. weighted average, etc.) re its potential to impact PL.

Point 2 is always problematic i.e. stock counts, because you're dealing with a number of moving targets; whatever the case strict time controls are vital, because if this involves any realtime POS; then stock quantity is always a moving target; so your count recon has to take into consideration stock that could have been sold but not yet reconciled; similarly that stock counted could be sold before the count itself is uploaded and reconciled, etc.

Best to keep reconciliation and sales as a separate processes; if realtime stock / sales analysis is required, then link it as an estimation based on the last recon. Note: your stock is only going to be as accurate as your last stock count; so accommodating rolling stock takes is not only a requirement for accurate auto reorder levels, but also combating theft, etc.
 
[)roi(];20713510 said:
As for point 1; it's a bit more complex than that; consider that the cost of the item will vary over time i.e. for your returns what book value will you'll use for the credit (e.g. weighted average, etc.) re its potential to impact PL.
Yes managing value of stock is more complex than just the qty. You have multiple methods of valuing stock, depending on your accounting practices. Some methods are harder to implement than others.

[)roi(];20713510 said:
Point 2 is always problematic i.e. stock counts, because you're dealing with a number of moving targets; whatever the case strict time controls are vital, because if this involves any realtime POS; then stock quantity is always a moving target; so your count recon has to take into consideration stock that could have been sold but not yet reconciled; similarly that stock counted could be sold before the count itself is uploaded and reconciled, etc.

Best to keep reconciliation and sales as a separate processes; if realtime stock / sales analysis is required, then link it as an estimation based on the last recon. Note: your stock is only going to be as accurate as your last stock count; so accommodating rolling stock takes is not only a requirement for accurate auto reorder levels, but also combating theft, etc.

Correct, theoretical stock qty 'drifts' away from physical stock qty because of user error, theft, system bugs etc.

OP has not really proviided much in the way of requirements....
 
Very good thread.

Further to inv'ing negative qty. One must bear is mind the possibility of inv errors (price or qty) and the time that is required to process a credit note, that requires level 1 , 2 or 3 authorization, during which stock could go into negative due to the inv error.

Can not agree with "Personally I prefer to keep all entities in separate tables. i.e. INVOICE, INVOICE_LINE, CREDIT_NOTE, CREDIT_NOTE_LINE. I dont like to 'pollute' an entity with data from another type of entity.".

In the accounting ledger debits and credit are mixed. Also complicates routines that update stock, sales, and on line document views etc. Doc number, type should be enough to id inv vs c/notes when ever required. But that what I used for 20 years.
 
Very good thread.

Further to inv'ing negative qty. One must bear is mind the possibility of inv errors (price or qty) and the time that is required to process a credit note, that requires level 1 , 2 or 3 authorization, during which stock could go into negative due to the inv error.
Agreed, in my experience user error is by far the biggest reason why lots of seemingly sensible 'rules' are broken. And you have to code for that. Coding the 'normal' flow is easy. But handling all the stuff ups that users will make, takes way more coding. And it is hard to anticipate those.

Can not agree with "Personally I prefer to keep all entities in separate tables. i.e. INVOICE, INVOICE_LINE, CREDIT_NOTE, CREDIT_NOTE_LINE. I dont like to 'pollute' an entity with data from another type of entity.".

In the accounting ledger debits and credit are mixed. Also complicates routines that update stock, sales, and on line document views etc. Doc number, type should be enough to id inv vs c/notes when ever required. But that what I used for 20 years.
Sure, I am aware that many/most accounting systems work this way. And it's not wrong at all, likely more correct from an accounting perspective. It's just that I tend to prefer it the other way. Entirely out of ignorance of course...:whistle:
 
Thanks for all the info and input so far. Thought all the info is much appreciated, my original question was in regards to how do you subtract the stock from the QTY field.

I have decided to have a "QTY On Hand", "QTY On Order", "QTY On Sales Order" column for each item. QTY On Hand would be all stock on the shelve. QTY On Order would be the QTY awaiting order from supplier, and QTY On Sales Order is QTY of item on orders for customer. Then using those fields I can calculate units available for resell etc.
 
Thanks for all the info and input so far. Thought all the info is much appreciated, my original question was in regards to how do you subtract the stock from the QTY field.

I have decided to have a "QTY On Hand", "QTY On Order", "QTY On Sales Order" column for each item. QTY On Hand would be all stock on the shelve. QTY On Order would be the QTY awaiting order from supplier, and QTY On Sales Order is QTY of item on orders for customer. Then using those fields I can calculate units available for resell etc.

That is perfect. But your 'spec' was a little unclear...

Might I add something else. Whenever you update a top-level qty, whether on hand, reserved etc. Always write an audit trail. E.g. if you cancel a Sales Order you QtyOnSalesOrder will decrement by X. Write an audit record that says:
SalesOrderNo: 123
TransactionType: SalesOrderCancellation
Qty: -X

It will save you lots of frustration trying to figure out why the qty is what it is. And you need it from an audit perspective.
 
That is perfect. But your 'spec' was a little unclear...

Might I add something else. Whenever you update a top-level qty, whether on hand, reserved etc. Always write an audit trail. E.g. if you cancel a Sales Order you QtyOnSalesOrder will decrement by X. Write an audit record that says:
SalesOrderNo: 123
TransactionType: SalesOrderCancellation
Qty: -X

It will save you lots of frustration trying to figure out why the qty is what it is. And you need it from an audit perspective.

Thanx for the tip. Didnt think of that, and I am sure it would save me a lot of time in the future. As those types of inconsistencies are not "if" but "when".

Again, thank you all for your valued input.
 
Top
Sign up to the MyBroadband newsletter
X