product name alone made required

This commit is contained in:
2026-08-29 12:46:14 +05:30
parent 29613e25ee
commit f4a2962981
7 changed files with 256 additions and 30 deletions

View File

@@ -426,9 +426,29 @@ export async function resolveBatch(batch: IngestBatch, signal?: AbortSignal): Pr
}
}
/** Every product a finished batch wrote, across its files. */
export function productsOf(batch: IngestBatch): IngestProduct[] {
return (batch.files ?? []).flatMap((file) => file.result?.products ?? []);
/**
* The products a finished run wrote, optionally narrowed to our own files.
*
* `filenames` is not optional in practice and should always be passed. An admin
* can assemble ONE run from several drops — the owning team's own words: "a run
* an admin assembled from several drops lists every file in it, so you may see
* filenames batched alongside your own" — so a run's manifest can contain other
* senders' products.
*
* Reading all of them was a real hazard, not a tidiness point. The sheet's price
* and opening stock are applied to whatever the manifest is matched against, so
* a product from someone else's sheet sharing a name with one of our rows would
* have been priced and stocked from OUR file, into OUR merchant's branch.
*
* Filtering by filename is the best this contract allows and it is not airtight:
* two senders can both upload `products.csv`. Narrowing by drop would be exact,
* and the run's files carry no drop reference to narrow by — worth asking for.
*/
export function productsOf(batch: IngestBatch, filenames?: readonly string[]): IngestProduct[] {
const wanted = filenames ? new Set(filenames) : null;
return (batch.files ?? [])
.filter((file) => !wanted || wanted.has(file.filename))
.flatMap((file) => file.result?.products ?? []);
}
/**