feat(prices): fiyat kayıtları, birim fiyat motoru ve analizde aylık maliyet
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import { z } from "zod";
|
||||
import { tr } from "../../i18n/tr";
|
||||
import { parseMoney } from "../money";
|
||||
|
||||
const v = tr.validation;
|
||||
const s = tr.productPrices.validation;
|
||||
const ymd = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, v.date);
|
||||
const id = (message: string) => z.string().regex(/^[a-f0-9]{24}$/i, message);
|
||||
|
||||
/** Elle fiyat girişi (kaynak: manual). Paket fiyatı TL; kampanyada geçerlilik sonu isteğe bağlı. */
|
||||
export const productPriceFormSchema = z
|
||||
.object({
|
||||
productId: id(s.product),
|
||||
storeId: id(s.store),
|
||||
date: ymd,
|
||||
price: z
|
||||
.string()
|
||||
.trim()
|
||||
.transform((x, ctx) => {
|
||||
const minor = parseMoney(x);
|
||||
if (minor === null || minor <= 0) {
|
||||
ctx.addIssue({ code: "custom", message: s.price });
|
||||
return z.NEVER;
|
||||
}
|
||||
return minor;
|
||||
}),
|
||||
isPromo: z.boolean(),
|
||||
promoUntil: z.preprocess((x) => (x === "" || x === undefined ? null : x), ymd.nullable()),
|
||||
note: z.string().trim().max(300).default(""),
|
||||
})
|
||||
.superRefine((x, ctx) => {
|
||||
if (x.isPromo && x.promoUntil && x.promoUntil < x.date)
|
||||
ctx.addIssue({ code: "custom", path: ["promoUntil"], message: s.promoUntil });
|
||||
})
|
||||
.transform(({ price, ...x }) => ({
|
||||
...x,
|
||||
priceMinor: price,
|
||||
promoUntil: x.isPromo ? x.promoUntil : null,
|
||||
}));
|
||||
export type ProductPriceFormInput = z.input<typeof productPriceFormSchema>;
|
||||
export type ProductPriceForm = z.output<typeof productPriceFormSchema>;
|
||||
Reference in New Issue
Block a user