Flow
Checks I would run before a move like this
1Trace one quantity
Follow it from where it is written to where it is priced, and name the field for what it holds.
2List rules on the link
Find every check that reads through the link you are about to cut.
3Probe the rounding
Test just below, at and just above one pack, with even and odd pack sizes.
4Copy before deleting
Save the rows before any bulk delete, so you can still see what went wrong.
Pressing round-to-full-cases left thirteen alone.
Say a case holds twelve. A cart line at five went up to twelve. Good. A line at thirteen stayed at thirteen, one case and a loose item, when it should have gone to two cases. The button only fixed lines below one case. Anything bigger, it skipped.
That bug is small. The thing under it is not. I got all of this from reading my own diffs, and I mark the parts that are guesses.
A cases column full of single items
The ordering system has a cart. Each cart line has a quantity field named for cases. But nothing treats it as cases. The suggestion step writes single items into it. Pricing works out a cost per item and multiplies by the quantity. The rounding button compares the quantity to the pack size. All of that only makes sense if the field holds items. The name is wrong.
The purchase order has the same problem. Its cases field gets the item count, and its case price gets the per-item price.
This kind of bug hangs around because both readings look fine. An order of 2 is normal whether it means two items or two cases. Nothing flags it. The total is just off by the pack size. And four separate parts of my system each read the field their own way.
One afternoon of pack math
That day I was moving the cart and the suggestions onto a catalog that each supplier owns. Pack size, name and price come from there now. Every place that read pack size had to change, and that's how I found the button.
Exact multiples now stay as they are, and everything else rounds up to the next full case.
Rounding up to the next full case means dividing by the pack size, rounding up, and multiplying back.
A minute after that change, I added a script that deletes every line in every cart. It has no filter. I don't know what the bad rows looked like, and if the script ran, it threw away the rows that could have told me.
Next was a commit I titled as fixing how suggestions store quantities. It doesn't change what gets stored. It adds a comment saying items go in the cases column. That's useful to know, but the title promised more than the change did.
That commit also changed two things I'm wary of. Suggestions now match sales to the new catalog through an outside ID, and skip sales they can't match. I think a product that fails to match would look like it never sells. And target stock levels used to be per store. Now every store writes to the same field, so the last store wins.
The hidden-product check went out with the old link
A store can hide a product so it can't be ordered. The cart and the suggestions used to check for that. Those checks went through a link to the old product record, and the new catalog has no such link. So every check was removed. The cart checks got a comment saying why; the suggestion one didn't.
I never decided hidden products should be orderable. The rule just fell out with the link. I haven't found where hidden state lives now, if anywhere, so I'm treating it as gone.
Reorder rules moved with the math
Suggestions now round up in half cases. With a case of twelve, thirteen becomes eighteen. With an odd pack size, half steps don't line up with full cases, by my math.
The default order for an item with no stock and no sales went from a full case to a half case and back within the hour. Overstocked items now get their reorders held back, like slow sellers. Cart edits round to the nearest item, but suggestions still round down. The migration also added fallbacks for a blank SKU, a placeholder brand and a zero price when there's no price, and dropped the case count from the supplier summary.
None of these changes had a test. If you're doing a move like this, the chart below lays out the four checks I wish had run, in order. The last one is copying rows before a bulk delete.
That script had no copy step, and I still don't know what the cart rows it targeted looked like.