From aeac76687b84be529ce64cf32b7d3f528a58c10a Mon Sep 17 00:00:00 2001 From: BOHA Date: Mon, 23 Mar 2026 18:42:41 +0100 Subject: [PATCH] fix: all item/sub-object schemas accept string numbers from form inputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed offers, orders, attendance, scope-templates schemas — quantity, unit_price, position, hours, minutes now use z.union([z.number(), z.string()]) with transform instead of bare z.number(). Co-Authored-By: Claude Opus 4.6 (1M context) --- src/schemas/attendance.schema.ts | 4 ++-- src/schemas/offers.schema.ts | 8 ++++---- src/schemas/orders.schema.ts | 8 ++++---- src/schemas/scope-templates.schema.ts | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/schemas/attendance.schema.ts b/src/schemas/attendance.schema.ts index 83989dc..e61b109 100644 --- a/src/schemas/attendance.schema.ts +++ b/src/schemas/attendance.schema.ts @@ -42,8 +42,8 @@ export const AttendanceLeaveSchema = z.object({ const ProjectLogSchema = z.object({ project_id: z.union([z.number(), z.string()]).transform(v => Number(v)), - hours: z.number().optional().default(0), - minutes: z.number().optional().default(0), + hours: z.union([z.number(), z.string()]).transform(v => Number(v) || 0).optional().default(0), + minutes: z.union([z.number(), z.string()]).transform(v => Number(v) || 0).optional().default(0), }); export const AttendancePunchSchema = z.object({ diff --git a/src/schemas/offers.schema.ts b/src/schemas/offers.schema.ts index 228f609..56876bd 100644 --- a/src/schemas/offers.schema.ts +++ b/src/schemas/offers.schema.ts @@ -3,18 +3,18 @@ import { z } from 'zod'; const QuotationItemSchema = z.object({ description: z.string().nullish(), item_description: z.string().nullish(), - quantity: z.number().optional().default(1), + quantity: z.union([z.number(), z.string()]).transform(v => Number(v) || 1).optional().default(1), unit: z.string().nullish(), - unit_price: z.number().optional().default(0), + unit_price: z.union([z.number(), z.string()]).transform(v => Number(v) || 0).optional().default(0), is_included_in_total: z.any().optional().default(true), - position: z.number().optional(), + position: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(), }); const ScopeSectionSchema = z.object({ title: z.string().nullish(), title_cz: z.string().nullish(), content: z.string().nullish(), - position: z.number().optional(), + position: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(), }); export const CreateQuotationSchema = z.object({ diff --git a/src/schemas/orders.schema.ts b/src/schemas/orders.schema.ts index c8718d0..e10955f 100644 --- a/src/schemas/orders.schema.ts +++ b/src/schemas/orders.schema.ts @@ -3,18 +3,18 @@ import { z } from 'zod'; const OrderItemSchema = z.object({ description: z.string().nullish(), item_description: z.string().nullish(), - quantity: z.number().optional().default(1), + quantity: z.union([z.number(), z.string()]).transform(v => Number(v) || 1).optional().default(1), unit: z.string().nullish(), - unit_price: z.number().optional().default(0), + unit_price: z.union([z.number(), z.string()]).transform(v => Number(v) || 0).optional().default(0), is_included_in_total: z.any().optional().default(true), - position: z.number().optional(), + position: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(), }); const OrderSectionSchema = z.object({ title: z.string().nullish(), title_cz: z.string().nullish(), content: z.string().nullish(), - position: z.number().optional(), + position: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(), }); export const CreateOrderFromQuotationSchema = z.object({ diff --git a/src/schemas/scope-templates.schema.ts b/src/schemas/scope-templates.schema.ts index 8712d37..2980690 100644 --- a/src/schemas/scope-templates.schema.ts +++ b/src/schemas/scope-templates.schema.ts @@ -4,7 +4,7 @@ const ScopeSectionSchema = z.object({ title: z.string().nullish(), title_cz: z.string().nullish(), content: z.string().nullish(), - position: z.number().optional(), + position: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(), }); export const CreateScopeTemplateSchema = z.object({