feat(catalog): add reviewed bulk edits and complete category duplication
This commit is contained in:
1 parent
0bedc04692
commit
55a47949f1
26 files changed
+2504
-85
No files matched your search
@@ -0,0 +1,81 @@
|
||||
import { z } from "zod";
|
||||
import { CatalogInputError } from "./hierarchy";
|
||||
import { offerIdSchema, offerInteger } from "./offer-input";
|
||||
|
||||
const priceChange = z
|
||||
.object({
|
||||
mode: z.enum(["set", "add", "percent"]),
|
||||
value: z.number().finite().min(-2147483648).max(2147483647),
|
||||
})
|
||||
.strict()
|
||||
.refine(
|
||||
(v) => v.mode === "percent" || Number.isInteger(v.value),
|
||||
"Set and add values must be whole numbers",
|
||||
);
|
||||
export const bulkOfferChangesSchema = z
|
||||
.object({
|
||||
costCredits: priceChange.optional(),
|
||||
costPoints: priceChange.optional(),
|
||||
pointsType: offerInteger.nonnegative().optional(),
|
||||
pageId: offerIdSchema.optional(),
|
||||
})
|
||||
.strict()
|
||||
.refine(
|
||||
(v) => Object.values(v).some((x) => x !== undefined),
|
||||
"Choose at least one field to change",
|
||||
);
|
||||
export const bulkOfferInputSchema = z
|
||||
.object({
|
||||
ids: z
|
||||
.array(offerIdSchema)
|
||||
.min(1)
|
||||
.max(500)
|
||||
.refine(
|
||||
(v) => new Set(v).size === v.length,
|
||||
"Selection contains duplicate offers",
|
||||
),
|
||||
changes: bulkOfferChangesSchema,
|
||||
})
|
||||
.strict();
|
||||
export type BulkOfferInput = z.infer<typeof bulkOfferInputSchema>;
|
||||
export type BulkOfferValues = {
|
||||
pageId: number;
|
||||
costCredits: number;
|
||||
costPoints: number;
|
||||
pointsType: number;
|
||||
};
|
||||
export type BulkOfferPreview = {
|
||||
fingerprint: string;
|
||||
changedCount: number;
|
||||
pages: Array<{ id: number; caption: string }>;
|
||||
rows: Array<{
|
||||
id: number;
|
||||
catalogName: string;
|
||||
before: BulkOfferValues;
|
||||
after: BulkOfferValues;
|
||||
}>;
|
||||
};
|
||||
export function projectBulkOffer(
|
||||
row: BulkOfferValues,
|
||||
changes: BulkOfferInput["changes"],
|
||||
): BulkOfferValues {
|
||||
const after = { ...row };
|
||||
for (const key of ["costCredits", "costPoints"] as const) {
|
||||
const change = changes[key];
|
||||
if (!change) continue;
|
||||
const value =
|
||||
change.mode === "set"
|
||||
? change.value
|
||||
: change.mode === "add"
|
||||
? row[key] + change.value
|
||||
: Math.round(row[key] * (1 + change.value / 100));
|
||||
if (!Number.isSafeInteger(value) || value < 0 || value > 2147483647)
|
||||
throw new CatalogInputError(
|
||||
"A resulting price is negative or exceeds the supported range",
|
||||
);
|
||||
after[key] = value;
|
||||
}
|
||||
if (changes.pointsType !== undefined) after.pointsType = changes.pointsType;
|
||||
if (changes.pageId !== undefined) after.pageId = changes.pageId;
|
||||
return after;
|
||||
}
|
||||
Reference in new issue
Block a user