Flow
Which parts a test checks and which I only read
1Record each line position
Tested: parsed lines carry their place in the sheet.
2Per-store targets
Tested: lines with different store lists give different targets per store.
3One numbered slot per line
Tested: names, distinct identifiers, and each slot keeps its own store list.
4Same numbers on every run
Tested: lines fed in reverse give the same identifiers.
5Stop when a store is short
Read, not tested: the save stops and nothing from it is kept.
6Remove stale links, add new ones
Read, not tested: the keep-list delete and the links.
7Reruns match existing buckets
Partly tested: the pack-size cleanup is checked, the looser lookup is only read.
Repeated lines on a supplier's sheet meant "send several," and the ordering system built one item from them.
This supplier picks the actual items for me. I just order a family, like one brand in one pack size. To ask for several items from a family, their sheet repeats the same line a few times. Each line also says which stores it's for.
The step that threw the count away
My import reads the sheet, plans a bucket per family and store, builds the products I can order, and saves it all at once. A bucket has a target: how many different items that store should carry from the family.
The planning step got the target right. It counted the repeated lines for each store. The build step then made one product per family, and the save linked that one product to the bucket. So a bucket could want several items and have one. Nothing checked. A repeated line looks like a paste mistake, so I can see how it got collapsed.
One product per repeated line
A family with one line keeps its old name. A family with several lines is no longer collapsed.
Before, the whole family became one product from its first priced row. Now the rows are sorted by sheet position and each becomes its own numbered product.
Each one keeps its own price, case size and list of stores.
Number them by sheet position
The lines are identical, so the numbers can't come from their content. The import now records where each line sits in the sheet and sorts by that. Without it, running the same sheet twice could give "selection two" to a different line. A test runs the lines in reverse and checks the numbers come out the same. The weak spot: if someone adds a line in the middle of a family, the numbers after it shift, and saved items could end up tied to the wrong stores.
Check before saving
When saving, each store keeps only the slots meant for it. If a store has fewer than its target, the whole save stops and names the bucket and store. If not, the save removes links that no longer apply and adds the right ones.
That removal step deletes anything not on a keep-list. An empty keep-list would delete everything. The count check above it stops that from happening, but nothing in the code points it out. If you build the same thing, put the guard right next to the delete.
Rerunning the same sheet
A second change stopped reruns from making look-alike buckets. Pack sizes written in different ways now match, and a looser lookup is only trusted when it finds exactly one bucket.
The test covers planning and building and stops there. The save step, the one that removes links, is the part I've only read.