Flow
What each path does with a hidden item
1Cart add or change
Says no and explains why.
2Old cart opened
Hidden lines are removed.
3Checkout
Removes them again and will not make an empty order.
4Hand-typed lines
Checked hardest of all.
5Suggestion report
Skips hidden items, so it never suggests a case of one.
Hiding a product from one store took one database write. Making sure that store could never order it took changes in half a dozen other places.
The ordering system now has two switches. A block stops one supplier's product for every store. A hide stops one product for one store. They live in different places. Both shipped in the same change.
How the hide is stored
A block turns off a flag on the link between supplier and product. A hide writes a negative number into the store's reorder threshold for that product and sets its stock count to zero. That's cheap. Every query that reads stock rows already sees it. But the field now means two things. Any code that reads it as a plain number has to know the trick. I'd give it a real column later.
Six ways a hidden item can still land on an order
Hiding it from the store's list is only one door. The others:
- adding to the cart
- changing a quantity in the cart
- a cart filled before the hide
- checkout
- lines typed in by hand when an order is sent again
- the suggestion report
Each one now checks, and each reacts in its own way. Adding or changing a cart line gets refused with a clear message. Opening a cart removes lines that were hidden or blocked after they went in. The buyer doesn't appear to be told. Checkout removes them again and won't make an empty order. That covers a cart left open while someone else hides the item. Hand-typed lines get checked hardest of all. The suggestion report and the store needs view just skip hidden items.
The check isn't one shared function. It's copied into each place, so a new door is only safe if someone remembers to copy it.
The report that could have suggested a case
The suggestion report now lists every product for every store. Rows with no sales and no stock get flagged, and any amount it suggests for them is rounded up to a full case. A hidden item looks exactly like that, since the hide zeroes its stock. As I read it, skipping hidden items there is what keeps a hide from turning into a suggestion to buy a case of it. I'd have missed that one.
Imports and order numbers
When a supplier's catalog is imported again, products missing from the file get blocked the same way a buyer would block them. Sales imports now replace old numbers instead of adding to them. Uploading a file twice no longer doubles anything.
Order numbers used to come from counting the day's orders, which breaks when a number is missing. They now use the highest number plus one. Two checkouts at the same moment could still pick the same number, and I haven't checked whether the database stops that.
What I can't back up
There are no tests, so every door I described is one I read about, not one I saw tried. The more practical gap is the way back: there's no way to unhide an item from the screen yet, so a hide made by mistake has no button to undo it.