diff --git a/src/schemas/warehouse.schema.ts b/src/schemas/warehouse.schema.ts new file mode 100644 index 0000000..119cc3f --- /dev/null +++ b/src/schemas/warehouse.schema.ts @@ -0,0 +1,242 @@ +import { z } from "zod"; + +// === Categories === +export const CreateCategorySchema = z.object({ + name: z.string().min(1, "Název je povinný"), + description: z.string().nullish(), + sort_order: z + .union([z.number(), z.string()]) + .transform((v) => Number(v)) + .optional() + .default(0), +}); +export const UpdateCategorySchema = z.object({ + name: z.string().min(1, "Název je povinný").optional(), + description: z.string().nullish(), + sort_order: z + .union([z.number(), z.string()]) + .transform((v) => Number(v)) + .optional(), +}); +export type CreateCategoryInput = z.infer; +export type UpdateCategoryInput = z.infer; + +// === Suppliers === +export const CreateSupplierSchema = z.object({ + name: z.string().min(1, "Název je povinný"), + ico: z.string().nullish(), + dic: z.string().nullish(), + contact_person: z.string().nullish(), + email: z.string().nullish(), + phone: z.string().nullish(), + address: z.string().nullish(), + notes: z.string().nullish(), + is_active: z + .preprocess((v) => v === true || v === 1 || v === "1", z.boolean()) + .optional() + .default(true), +}); +export const UpdateSupplierSchema = z.object({ + name: z.string().min(1, "Název je povinný").optional(), + ico: z.string().nullish(), + dic: z.string().nullish(), + contact_person: z.string().nullish(), + email: z.string().nullish(), + phone: z.string().nullish(), + address: z.string().nullish(), + notes: z.string().nullish(), + is_active: z + .preprocess((v) => v === true || v === 1 || v === "1", z.boolean()) + .optional(), +}); +export type CreateSupplierInput = z.infer; +export type UpdateSupplierInput = z.infer; + +// === Locations === +export const CreateLocationSchema = z.object({ + code: z.string().min(1, "Kód je povinný"), + name: z.string().min(1, "Název je povinný"), + description: z.string().nullish(), + is_active: z + .preprocess((v) => v === true || v === 1 || v === "1", z.boolean()) + .optional() + .default(true), +}); +export const UpdateLocationSchema = z.object({ + code: z.string().min(1, "Kód je povinný").optional(), + name: z.string().min(1, "Název je povinný").optional(), + description: z.string().nullish(), + is_active: z + .preprocess((v) => v === true || v === 1 || v === "1", z.boolean()) + .optional(), +}); +export type CreateLocationInput = z.infer; +export type UpdateLocationInput = z.infer; + +// === Items === +const UNIT_LIST = ["ks", "m", "kg", "bal", "sada", "m2", "m3", "l"] as const; +export const UnitEnum = z.enum(UNIT_LIST); +export type Unit = z.infer; + +export const CreateItemSchema = z.object({ + item_number: z.string().nullish(), + name: z.string().min(1, "Název je povinný"), + description: z.string().nullish(), + category_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + unit: UnitEnum, + min_quantity: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + notes: z.string().nullish(), + is_active: z + .preprocess((v) => v === true || v === 1 || v === "1", z.boolean()) + .optional() + .default(true), +}); +export const UpdateItemSchema = z.object({ + item_number: z.string().nullish(), + name: z.string().min(1, "Název je povinný").optional(), + description: z.string().nullish(), + category_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + unit: UnitEnum.optional(), + min_quantity: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + notes: z.string().nullish(), + is_active: z + .preprocess((v) => v === true || v === 1 || v === "1", z.boolean()) + .optional(), +}); +export type CreateItemInput = z.infer; +export type UpdateItemInput = z.infer; + +// === Receipts === +export const ReceiptLineSchema = z.object({ + item_id: z.union([z.number(), z.string()]).transform((v) => Number(v)), + quantity: z.union([z.number(), z.string()]).transform((v) => Number(v)), + unit_price: z.union([z.number(), z.string()]).transform((v) => Number(v)), + location_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + notes: z.string().nullish(), +}); + +export const CreateReceiptSchema = z.object({ + supplier_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + delivery_note_number: z.string().nullish(), + delivery_note_date: z.union([z.string(), z.null()]).nullish(), + notes: z.string().nullish(), + lines: z + .array(ReceiptLineSchema) + .min(1, "Příjem musí obsahovat alespoň jednu položku"), +}); +export const UpdateReceiptSchema = z.object({ + supplier_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + delivery_note_number: z.string().nullish(), + delivery_note_date: z.union([z.string(), z.null()]).nullish(), + notes: z.string().nullish(), + lines: z + .array(ReceiptLineSchema) + .min(1, "Příjem musí obsahovat alespoň jednu položku") + .optional(), +}); +export type CreateReceiptInput = z.infer; +export type UpdateReceiptInput = z.infer; +export type ReceiptLineInput = z.infer; + +// === Issues === +export const IssueLineSchema = z.object({ + item_id: z.union([z.number(), z.string()]).transform((v) => Number(v)), + batch_id: z + .union([z.number(), z.string()]) + .transform((v) => Number(v)) + .nullish(), + quantity: z.union([z.number(), z.string()]).transform((v) => Number(v)), + location_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + reservation_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + notes: z.string().nullish(), +}); + +export const CreateIssueSchema = z.object({ + project_id: z.union([z.number(), z.string()]).transform((v) => Number(v)), + notes: z.string().nullish(), + lines: z + .array(IssueLineSchema) + .min(1, "Výdej musí obsahovat alespoň jednu položku"), +}); +export const UpdateIssueSchema = z.object({ + project_id: z + .union([z.number(), z.string()]) + .transform((v) => Number(v)) + .optional(), + notes: z.string().nullish(), + lines: z + .array(IssueLineSchema) + .min(1, "Výdej musí obsahovat alespoň jednu položku") + .optional(), +}); +export type CreateIssueInput = z.infer; +export type UpdateIssueInput = z.infer; +export type IssueLineInput = z.infer; + +// === Reservations === +export const CreateReservationSchema = z.object({ + item_id: z.union([z.number(), z.string()]).transform((v) => Number(v)), + project_id: z.union([z.number(), z.string()]).transform((v) => Number(v)), + quantity: z.union([z.number(), z.string()]).transform((v) => Number(v)), + notes: z.string().nullish(), +}); +export type CreateReservationInput = z.infer; + +// === Inventory === +export const InventoryLineSchema = z.object({ + item_id: z.union([z.number(), z.string()]).transform((v) => Number(v)), + location_id: z + .union([z.number(), z.string(), z.null()]) + .transform((v) => (v === null ? null : Number(v))) + .nullish(), + actual_qty: z.union([z.number(), z.string()]).transform((v) => Number(v)), + notes: z.string().nullish(), +}); + +export const CreateInventorySessionSchema = z.object({ + notes: z.string().nullish(), + lines: z + .array(InventoryLineSchema) + .min(1, "Inventura musí obsahovat alespoň jednu položku"), +}); +export const UpdateInventorySessionSchema = z.object({ + notes: z.string().nullish(), + lines: z + .array(InventoryLineSchema) + .min(1, "Inventura musí obsahovat alespoň jednu položku") + .optional(), +}); +export type CreateInventorySessionInput = z.infer< + typeof CreateInventorySessionSchema +>; +export type UpdateInventorySessionInput = z.infer< + typeof UpdateInventorySessionSchema +>; +export type InventoryLineInput = z.infer;