feat(catalog): add reviewed bulk edits and complete category duplication
CI / check (push) Successful in 1m14s
CI / deploy (push) Successful in 1m11s

This commit is contained in:
Simo committed 2026-09-06 20:25:19 +02:00
1 parent 0bedc04692
commit 55a47949f1
26 files changed
+2504 -85

No files matched your search

+68
View File
@@ -0,0 +1,68 @@
"use server";
import { revalidatePath } from "next/cache";
import type { BulkOfferInput } from "@/features/catalog/domain/bulk-offers";
import {
applyBulkOffersCommand,
listBulkOfferDestinationsCommand,
previewBulkOffersCommand,
} from "@/features/catalog/server/bulk-offers";
import { catalogFailure } from "@/features/catalog/server/errors";
import { sendCatalogUpdate } from "@/features/catalog/server/sync-status";
import { requirePermission } from "@/lib/admin/guard";
import { logger } from "@/lib/logger";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { withCatalogExport } from "@/lib/services/catalog-git-queue";
export async function previewBulkOffers(input: BulkOfferInput) {
await requirePermission(PERMS.CATALOG_VIEW);
try {
return { ok: true as const, data: await previewBulkOffersCommand(input) };
} catch (error) {
return { ok: false as const, error: catalogFailure(error).message };
}
}
export async function applyBulkOffers(
input: BulkOfferInput,
fingerprint: string,
) {
const staff = await requirePermission(PERMS.CATALOG_EDIT);
try {
return await withCatalogExport(async () => {
const data = await applyBulkOffersCommand(input, fingerprint);
if (data.changedCount > 0) {
await logAudit({
userId: staff.id,
action: "catalog_offers_bulk_update",
target: "catalog",
after: {
ids: input.ids,
changes: input.changes,
changedCount: data.changedCount,
},
}).catch((error) =>
logger.error("Catalog bulk update committed; audit write failed", {
module: "catalog",
error,
}),
);
await sendCatalogUpdate();
revalidatePath("/admin/catalog", "layout");
}
return { ok: true as const, data };
});
} catch (error) {
return { ok: false as const, error: catalogFailure(error).message };
}
}
export async function getBulkOfferDestinations() {
await requirePermission(PERMS.CATALOG_VIEW);
try {
return {
ok: true as const,
data: await listBulkOfferDestinationsCommand(),
};
} catch (error) {
return { ok: false as const, error: catalogFailure(error).message };
}
}