fix(catalog): route item-table writes to the catalog they belong to
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 32s
CI / tests-integration (push) Successful in 1m43s
CI / tests-unit (push) Successful in 1m48s
CI / tests-ui (push) Successful in 2m37s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m16s
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 32s
CI / tests-integration (push) Successful in 1m43s
CI / tests-unit (push) Successful in 1m48s
CI / tests-ui (push) Successful in 2m37s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m16s
The items table is shared between both catalogs, but its four mutating actions were normal-only: moving, reordering, creating and updating a Builder Club offer wrote to catalog_items, so a BC edit either landed in the wrong catalog or hit an unknown column. Pass the catalog from the table through the actions and let the server resolve it. BC rows have no price, points or currency column, so the BC commands strip those fields instead of rejecting them. Moving and reordering now share one command that locks the category and writes the table for the same catalog, and BC writes revalidate the BC route.
This commit is contained in:
1 parent
e0efbef30d
commit
cede541813
3 files changed
+155
-50
No files matched your search
@@ -217,18 +217,56 @@ export async function reorderOffersCommand(
|
||||
});
|
||||
}
|
||||
export async function moveOffersCommand(ids: number[], targetPageId: number) {
|
||||
return moveOffersToPage(ids, targetPageId, "normal");
|
||||
}
|
||||
|
||||
/** BC offers move between BC categories; the lock and the write have to agree. */
|
||||
export async function moveBcOffersCommand(ids: number[], targetPageId: number) {
|
||||
return moveOffersToPage(ids, targetPageId, "bc");
|
||||
}
|
||||
|
||||
async function moveOffersToPage(
|
||||
ids: number[],
|
||||
targetPageId: number,
|
||||
kind: OfferKind,
|
||||
) {
|
||||
distinctOfferIds(ids);
|
||||
offerIdSchema.parse(targetPageId);
|
||||
if (!ids.length) return;
|
||||
const table = offerTable(kind);
|
||||
return db.transaction(async (tx) => {
|
||||
await lockPage(tx, targetPageId);
|
||||
await lockedOffers(tx, ids);
|
||||
await lockPage(tx, targetPageId, kind);
|
||||
await lockedOffers(tx, ids, kind);
|
||||
await tx.execute(
|
||||
sql`UPDATE ${CatalogItems} SET page_id=${String(targetPageId)} WHERE id IN (${sql.join(ids, sql`, `)})`,
|
||||
sql`UPDATE ${table} SET page_id=${String(targetPageId)} WHERE id IN (${sql.join(ids, sql`, `)})`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/** Same as the normal reorder, against the BC offers table. */
|
||||
export async function reorderBcOffersCommand(
|
||||
orders: Array<{ id: number; orderNumber: number }>,
|
||||
) {
|
||||
const ids = distinctOfferIds(orders.map((row) => row.id));
|
||||
for (const row of orders) offerInteger.parse(row.orderNumber);
|
||||
if (!ids.length) return;
|
||||
return db.transaction(async (tx) => {
|
||||
const offers = await lockedOffers(tx, ids, "bc");
|
||||
const pageId = offers[0]?.pageId;
|
||||
if (pageId !== undefined) {
|
||||
const nums = orders.map((r) => r.orderNumber);
|
||||
if (new Set(nums).size !== nums.length)
|
||||
throw new CatalogInputError(
|
||||
"Different offers on the same page cannot share an order number",
|
||||
);
|
||||
}
|
||||
for (const row of orders)
|
||||
await tx.execute(
|
||||
sql`UPDATE ${CatalogItemsBc} SET order_number=${row.orderNumber} WHERE id=${row.id}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/** Call the allocator before entering this command; only the insert uses its transaction. */
|
||||
export async function createOfferCommand<T>(
|
||||
kind: OfferKind,
|
||||
|
||||
Reference in new issue
Block a user