Best approaches to eCommerce stock management - e-commerce

What are the best (or perhaps most commonly used) approaches for coordinating actual stock quantities with that shown or offered for sale with a shopping cart?
Thanks in advance,
Matt

Well, you have several problems.
At a basic level, its "easy". Simply use classic transactional processing techniques to maintain the stock numbers and the order entry lines against the stock. If you have 10 available, and someone orders 1, then commit the line item with a qty of 1 at the same time you increment the "committed" qty on the inventory item. When you ship the item, remove one from In Stock, and one from Committed. In Stock - Committed = Available.
So:
In Stock Committed Available
Before: 10 0 10
Ordered: 10 1 9
Shipped: 9 0 9
The down side is that involves a bunch of locking, which can affect concurrency. Depending on your traffic this may or may not be an issue. Then you're work with on the fly counting of ordered items against stock, and you end up with race conditions. But it's really just a fact of life in business.
But, either way, regardless of how you commit the entry in to your database, it doesn't mean that the item will actually ship.
The In Stock number could simply be wrong. It could have been miskeyed, stock may be damaged, "employee shrinkage", etc. All sorts of things can go wrong. So, any commitment you make to a customer that you'll actually SHIP what you've promised has to have that little * next to it as a disclaimer.
Then you get in to the whole back ordering, cancellation and fulfillment issues.

Related

Does transaction locks the row to prevent the data inconsistancy

I am new to MSSQL and creating a website where Customers can place orders.
Each order may have multiple items with any number of quantity.
I am interested in before saving my order to check if the desired quantity is available for each item, if yes then I will place the order and update the items inventory, otherwise I want to rollback.
But at the same time I want that any other order should wait till first transaction is finished. So that up updates don't overwrite the changes and produce inconsistency.
If each order is processed within a transaction, is it enough or do I have to consider something else too?
If you go on any Online retail website, you will notice that you go through the shop, buying stuff (not actually buying but being added to a basket) and once you have completed your shopping you go to Checkout that is, where you are asked to provide payment details etc.
So the idea is, the website shows everything (that has at least 1 stock item) to every customer, At this point no item inventory is being updated or inserted, at the checkout stage a complete order is compiled and submitted to system, (at this stage you will do the actual updates/inserts to item stock inventory) now how you want to handle the orders is entirely up to you.
Do you want to rollback entire order when any one item has less stock than
the quantity ordered?
Do you want to commit all order lines and only rollback those order lines where the items has less stock than quantity ordered?
Or do you want to place a provisional
order regardless of the stock availability and manipulate the delivery date?
Depending on what path you chose to go with (this should be a business decision a developer shouldn't be making these decisions) there is a lot of flexibility, but one thing you never do is as soon as someone has select to buy an item, you update the inventory. All this should be done right in the end of the Purchase process and all should be done at Once.

Real-Time File Lock Handling

I'm working on a multi-terminal POS system. Inventory levels and availability is quite straightforward when dealing with physical goods, but how would we handle this when dealing with virtual inventory? I mean, what if the stock level for item X is 1, and two, or more, operators are trying to place an order for it? Or, even if the balance available quantity is more than just 1, should the quantity be deducted or locked from the inventory file when an operator is processing an order for it, and then reinstated if the order is cancelled?
Thanks in advance.

Recurring Orders

Hi everyone I'm working on a school project, and for my project I chose to create an ecommerce system that can process recurring orders. This is for my final project, I'll be graduating in May with an associates in computer science.
Keep in mind this is no where a final solution and it's basically a jumping off point for this database design.
A little background on the business processes.
- Customer will order a product, and will specify during checkout whether it is a one time order or a weekly/monthly order.
- Customer will specify a location in which to pick up their order (this location is specific only to the order)
- If the value of the order > 25.00 then it is accepted otherwise it is rejected.
- This will populate the orders_test and order_products_test tables respectively
Person on the back end will have a report generated for deliveries for the day based on these two tables.
They will be able to print it off and it will generate a list of what items go to what location.
Based on the following criteria.
date_of_next_scheduled_delivery = current date
remaining_deliveries > 0
Once they are satisfied with the delivery list they will press "Process Deliveries" button.
This will adjust the order_products_test table as follows
Subtract 1 from remaining_deliveries
Insert current date into date_of_last_delivery_processed
Based on delivery_frequency (i.e. once, weekly, monthly) it will change the date_of_next_scheduled_delivery
status values in the order_products_test table can either be active, hold, or canceled, expired
I just would like some opinions if I am approaching this correctly or if I should scratch this approach and start over again.
A few thoughts, though not necessarily complete (there's a lot to your question, but hopefully these points help):
I don't think you need to keep track of remaining deliveries. You only have 2 options - a one time order, or a recurring order. In both cases, there's no sense in calculating remaining deliveries. It's never leveraged.
In terms of tracking the next delivery date, you can just keep track of the day of the order. If it's recurring -- monthly or weekly, regardless -- everything is calculable from that first date. Most DB systems (MySQL, SQL Server, Oracle, etc) support more than enough date computation flexibility so that you can calculate this on the fly, as opposed to maintaining such a known schedule.
If the delivery location is only specific to the order, I see no use in creating a separate table for it -- it's functionally dependent on the order, you should keep it in the same table as the order. For most e-commerce systems, this is not the case because they tend to associate a list of delivery locations with accounts, which they prompt you about when you order more than once (e.g., Amazon).
Given the above, I bet you can just get away with 2 of your 4 tables above -- Account and Order. But again, if delivery locations are associated with Accounts, I would indeed break that out. (but your question above doesn't suggest that)
Do not name your tables with a "_test" suffix -- it's confusing.

Have 2 separate tables or an additional field in 1 table?

I am making a small personal application regarding my trade of shares of various companies.
The actions can be selling shares of a company or buying. Therefore, the details to be saved in both cases would be:
Number of Shares
Average Price
Would it be better to use separate tables for "buy" and "sell" or just use one table for "trade" and keep a field that demarcates "buy" from "sell"?
Definitely the latter case - one table, simple one field (boolean) defining whether it's selling or buying. You should define tables by entities, not by actions taken on them.
This is actually a tricky one. The table you're talking about is basically a trade table, detailing all your buys and sells.
In that sense, you would think it would make sense to have both buys and sells in a single table.
However, in many jurisdictions, there is extra information for a sell order. That piece of information is which buy order to offset it against (for capital gains or profit purposes). While this is not necessary in a strict first-bought, first-sold (FBFS) environment, that's by no means the only possibility.
For example, under Australian law, you can actually offset a sale against your most recent purchase, as long as you have the rationale written down in clear language before-hand. Even though my company follow FBFS, I am allowed to receive bonus issues or supplemental shares which I can then sell immediately. These are offset against the most recent shares bought, not ones I've held for X number of years (this is often handy to minimise taxes payable).
If you follow a strict FBFS, then you don't need that extra information and your trades are symmetrical. Even where they're not, I've implemented it in one table with the extra information, useless for buy orders of course. That seemed the easiest way to go.
You could do it as two asymmetrical tables but that makes queries a bit more problematic since you often need to pull data from both tables. My advice is to stick with a single table with the extra information if needed.
I would also never store the average price. I prefer the quantity, the price per share and the brokerage costs. Every other figure can be calculated from those three, for example:
AvgPrice = (Brokerage + SharePrice * ShareQuant) / ShareQuant
but it's sometimes impossible to work backwards from just the average price, since you don't know what the brokerage was.
And I wouldn't have a boolean for buy/sell, it's just as easy to use negative numbers for the sell orders and it makes balance-sheet-type calculations a lot easier since you just sum values irrespective of the order type instead of needing to negate some of them depending on that order type.
Update: If, as you seem to indicate, you're only going to store aggregate information for each company, I would go for the following:
Companies:
CompanyId primary key
CompanyCode indexed
CompanyName
CompanyBuyQuant
CompanyBuyAvgPrice
CompanySellQuant
CompanySellAvgPrice
then you update the individual columns depending on whether it's a buy or sell. You don't need a separate row for the buy/sell stuff. When the company is first added, both quantities and prices are set to 0.
Your entity is now the company so this makes more sense. One thing you may want to consider is to store the aggregate values of shares bought and sold rather than the average buy and sell prices. That will simplify your update calculations and you can still easily get the averages by dividing the aggregate by the quantity.
So, the following table:
Companies:
CompanyId primary key
CompanyCode indexed
CompanyName
CompanyBuyQuant
CompanyBuyValue
CompanySellQuant
CompanySellValue
When adding a company, set all quanities and values to 0,
When buying M shares at N dollars each, add M to CompanyBuyQuant and N * M to CompanyBuyValue.
When selling M shares at N dollars each, add M to CompanySellQuant and N * M to CompanySellValue.
Get average buy price as CompanyBuyValue / CompanyBuyQuant.
Get average sell price as CompanySellValue / CompanySellQuant.
I'd go with a single table.
You can use negative quantities to indicate a sell. This is a fairly standard sort of indication. Subtraction is the same as adding a negative number!
One table. Each row/item is a trade, whether it's buy or sell.
Also, the aggregate of the quantity column will give you your current position. And cash too (-1 x quantity x price**) aggregated.
Buy or sell if inferred by the sign of the quantity: no need for separate column, unless you want to make a computed column derived from quantity.
**cash: When you sell (negative quantity) you get cash back (positive cash), hence -1 multiplier in case anyone wonders.
"Trade" can be ambiguous and it's not entirely clear to me what you want to do here. Are you interested in storing only your current position in each share or also the history of transactions that show how the position developed?
If you just want to record your holding ("position" might be a better word if you can be short) then I'd simply record for each share the number held. You mention average price, but I'd be cautious about that if you expect at any time to be able to sell part of a holding. What's the average price if you buy 100 at 50, 100 at 60 and sell 50 at 70?
Unless you expect your buy and sell transactions to number in the millions, I'd be more inclined to record each individual purchase or sale as a separate row in a single table and show the totals on demand as the derived results of a simple query.

track sales for week/month and find the best sellers

Lets say I have a website that sells widgets. I would like to do something similar to a tag cloud tracking best sellers. However, due to constantly aquiring and selling new widgets, I would like the sales to decay on a weekly time scale.
I'm having problems puzzling out how store and manipulate this data and have it decay properly over time so that something that was an ultra hot item 2 months ago but has since tapered off doesn't show on top of the list over the current best sellers. What would be the logic and database design for this?
Part 1: You have to have tables storing the data that you want to report on. Date/time sold is obviously key. If you need to work in decay factors, that raises the question: for how long is the data good and/or relevant? At what point in time as the "value" of the data decayed so much that you no longer care about it? When this point is reached for any given entry in the database, what do you do--keep it there but ensure it gets factored out of all subsequent computations? Or do you archive it--copy it to a "history" table and delete it from your main "sales" table? This is relevant, as it has to be factored into your decay formula (as well as your capacity planning, annual reporting requirements, and who knows what all else.)
Part 2: How much thought has been given to the decay formula that you want to use? There's no end of detail you can work into this. Options and factors to wade through include but are not limited to:
Simple age-based. Everything before the cutoff date counts as 1; everything after counts as 0. Sum and you're done.
What's the cutoff date? Precisly 14 days ago, to the minute? Midnight as of two Saturdays ago from (now)?
Does the cutoff date depend on the item that was sold? If some items are hot but some are not, does that affect things? What if you want to emphasize some things (the expensive/hard to sell ones) over others (the fluff you'd sell anyway)?
Simple age-based decays are trivial, but can be insufficient. Time to go nuclear.
Perhaps you want some kind of half-life, Dr. Freeman?
Everything sold is "worth" X, where the value of X is either always the same or varies on the item sold. And the value of X can decay over time.
Perhaps the value of X decreased by one-half every week. Or ever day. Or every month. Or (again) it may vary depending on the item.
If you do half-lifes, the value of X may never reach zero, and you're stuck tracking it forever (which is why I wrote "part 1" first). At some point, you probably need some kind of cut-off, some point after which you just don't care. X has decreased to one-tenth the intial value? Three months have passed? Either/or but the "range" depends on the inherent valud of the item?
My real point here is that how you calculate your decay rate is far more important than how you store it in the database. So long as the data's there that the formalu needs to do it's calculations, you should be good. And if you only need the last month's data to do this, you should perhaps move everything older to some kind of archive table.
you could just count the sales for the last month/week/whatever, and sort your items according to that.
if you want you can always add the total amonut of sold items into your formula.
You might have a table which contains the definitions of the pointing criterion (most sales, most this, most that, etc.), then for a given period, store in another table the attribution of points for each of the criterion defined in the criterion table. Obviously, a historical table will be used to store the score for each sellers for a given period or promotion, call it whatever you want.
Does it help a little?