feat: add Zod validation schemas for all domain routes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-03-23 08:57:38 +01:00
parent a4303b0188
commit d2b22e9399
32 changed files with 819 additions and 140 deletions

View File

@@ -0,0 +1,97 @@
import { z } from 'zod';
export const AttendanceNotesSchema = z.object({
notes: z.string().nullish(),
});
export const AttendanceUpdateAddressSchema = z.object({
address: z.string().max(500).nullish(),
punch_action: z.string().optional().default('arrival'),
});
export const AttendanceSwitchProjectSchema = z.object({
project_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
});
export const AttendanceBalancesSchema = z.object({
user_id: z.union([z.number(), z.string()]).transform(v => Number(v)),
year: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
action_type: z.string(),
vacation_total: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
vacation_used: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
sick_used: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
});
export const AttendanceBulkSchema = z.object({
month: z.string().regex(/^\d{4}-\d{2}$/, 'Měsíc je povinný (formát YYYY-MM)'),
user_ids: z.array(z.number()).min(1, 'Vyberte alespoň jednoho zaměstnance'),
arrival_time: z.string().optional().default('08:00'),
departure_time: z.string().optional().default('16:30'),
break_start_time: z.string().optional().default('12:00'),
break_end_time: z.string().optional().default('12:30'),
});
export const AttendanceLeaveSchema = z.object({
user_id: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
date_from: z.string().min(1, 'Datum je povinné'),
date_to: z.string().optional(),
leave_type: z.string().optional().default('vacation'),
leave_hours: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
notes: z.string().nullish(),
});
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),
});
export const AttendancePunchSchema = z.object({
punch_action: z.string(),
latitude: z.union([z.number(), z.string(), z.null()]).optional(),
longitude: z.union([z.number(), z.string(), z.null()]).optional(),
accuracy: z.union([z.number(), z.string(), z.null()]).optional(),
address: z.string().max(500).nullish(),
});
export const CreateAttendanceSchema = z.object({
user_id: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
shift_date: z.string(),
arrival_time: z.string().nullish(),
arrival_lat: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
arrival_lng: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
arrival_accuracy: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
arrival_address: z.string().nullish(),
departure_time: z.string().nullish(),
departure_lat: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
departure_lng: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
departure_accuracy: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
departure_address: z.string().nullish(),
notes: z.string().nullish(),
project_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
leave_type: z.string().optional().default('work'),
leave_hours: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
project_logs: z.array(ProjectLogSchema).optional(),
});
export const UpdateAttendanceSchema = z.object({
arrival_time: z.union([z.string(), z.null()]).optional(),
departure_time: z.union([z.string(), z.null()]).optional(),
break_start: z.union([z.string(), z.null()]).optional(),
break_end: z.union([z.string(), z.null()]).optional(),
notes: z.string().nullish(),
project_id: z.union([z.number(), z.string(), z.null()]).optional(),
leave_type: z.string().optional(),
leave_hours: z.union([z.number(), z.string(), z.null()]).optional(),
project_logs: z.array(ProjectLogSchema).optional(),
});
export type AttendanceNotesInput = z.infer<typeof AttendanceNotesSchema>;
export type AttendanceUpdateAddressInput = z.infer<typeof AttendanceUpdateAddressSchema>;
export type AttendanceSwitchProjectInput = z.infer<typeof AttendanceSwitchProjectSchema>;
export type AttendanceBalancesInput = z.infer<typeof AttendanceBalancesSchema>;
export type AttendanceBulkInput = z.infer<typeof AttendanceBulkSchema>;
export type AttendanceLeaveInput = z.infer<typeof AttendanceLeaveSchema>;
export type AttendancePunchInput = z.infer<typeof AttendancePunchSchema>;
export type CreateAttendanceInput = z.infer<typeof CreateAttendanceSchema>;
export type UpdateAttendanceInput = z.infer<typeof UpdateAttendanceSchema>;

View File

@@ -0,0 +1,26 @@
import { z } from 'zod';
export const CreateBankAccountSchema = z.object({
account_name: z.string().nullish(),
bank_name: z.string().nullish(),
account_number: z.string().nullish(),
iban: z.string().nullish(),
bic: z.string().nullish(),
currency: z.string().optional().default('CZK'),
is_default: z.any().optional().default(false),
position: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(0),
});
export const UpdateBankAccountSchema = z.object({
account_name: z.string().nullish(),
bank_name: z.string().nullish(),
account_number: z.string().nullish(),
iban: z.string().nullish(),
bic: z.string().nullish(),
currency: z.string().optional(),
is_default: z.any().optional(),
position: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
});
export type CreateBankAccountInput = z.infer<typeof CreateBankAccountSchema>;
export type UpdateBankAccountInput = z.infer<typeof UpdateBankAccountSchema>;

View File

@@ -0,0 +1,21 @@
import { z } from 'zod';
export const UpdateCompanySettingsSchema = z.object({
company_name: z.string().nullish(),
street: z.string().nullish(),
city: z.string().nullish(),
postal_code: z.string().nullish(),
country: z.string().nullish(),
company_id: z.string().nullish(),
vat_id: z.string().nullish(),
quotation_prefix: z.string().nullish(),
default_currency: z.string().nullish(),
order_type_code: z.string().nullish(),
invoice_type_code: z.string().nullish(),
default_vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
require_2fa: z.any().optional(),
custom_fields: z.array(z.any()).optional(),
supplier_field_order: z.array(z.any()).optional(),
});
export type UpdateCompanySettingsInput = z.infer<typeof UpdateCompanySettingsSchema>;

View File

@@ -0,0 +1,28 @@
import { z } from 'zod';
export const CreateCustomerSchema = z.object({
name: z.string().min(1, 'Název zákazníka je povinný'),
street: z.string().nullish(),
city: z.string().nullish(),
postal_code: z.string().nullish(),
country: z.string().nullish(),
company_id: z.string().nullish(),
vat_id: z.string().nullish(),
custom_fields: z.array(z.any()).optional(),
customer_field_order: z.array(z.string()).optional(),
});
export const UpdateCustomerSchema = z.object({
name: z.string().optional(),
street: z.string().nullish(),
city: z.string().nullish(),
postal_code: z.string().nullish(),
country: z.string().nullish(),
company_id: z.string().nullish(),
vat_id: z.string().nullish(),
custom_fields: z.array(z.any()).optional(),
customer_field_order: z.array(z.string()).optional(),
});
export type CreateCustomerInput = z.infer<typeof CreateCustomerSchema>;
export type UpdateCustomerInput = z.infer<typeof UpdateCustomerSchema>;

View File

@@ -0,0 +1,58 @@
import { z } from 'zod';
const InvoiceItemSchema = z.object({
description: z.string().nullish(),
quantity: z.number().optional().default(1),
unit: z.string().nullish(),
unit_price: z.number().optional().default(0),
vat_rate: z.number().optional().default(21.0),
position: z.number().optional(),
});
export const CreateInvoiceSchema = z.object({
invoice_number: z.string().nullish(),
order_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
customer_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
status: z.string().optional().default('issued'),
currency: z.string().optional().default('CZK'),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(21.0),
apply_vat: z.any().optional().default(true),
payment_method: z.string().nullish(),
constant_symbol: z.string().nullish(),
bank_name: z.string().nullish(),
bank_swift: z.string().nullish(),
bank_iban: z.string().nullish(),
bank_account: z.string().nullish(),
issue_date: z.string().nullish(),
due_date: z.string().nullish(),
tax_date: z.string().nullish(),
issued_by: z.string().nullish(),
notes: z.string().nullish(),
internal_notes: z.string().nullish(),
items: z.array(InvoiceItemSchema).optional(),
});
export const UpdateInvoiceSchema = z.object({
status: z.string().optional(),
currency: z.string().optional(),
payment_method: z.string().nullish(),
constant_symbol: z.string().nullish(),
bank_name: z.string().nullish(),
bank_swift: z.string().nullish(),
bank_iban: z.string().nullish(),
bank_account: z.string().nullish(),
issued_by: z.string().nullish(),
customer_id: z.union([z.number(), z.string(), z.null()]).optional(),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
apply_vat: z.any().optional(),
issue_date: z.union([z.string(), z.null()]).optional(),
due_date: z.union([z.string(), z.null()]).optional(),
tax_date: z.union([z.string(), z.null()]).optional(),
notes: z.string().nullish(),
internal_notes: z.string().nullish(),
paid_date: z.union([z.string(), z.null()]).optional(),
items: z.array(InvoiceItemSchema).optional(),
});
export type CreateInvoiceInput = z.infer<typeof CreateInvoiceSchema>;
export type UpdateInvoiceInput = z.infer<typeof UpdateInvoiceSchema>;

View File

@@ -0,0 +1,16 @@
import { z } from 'zod';
export const CreateLeaveRequestSchema = z.object({
leave_type: z.string().min(1, 'Typ nepřítomnosti je povinný'),
date_from: z.string().min(1, 'Datum od je povinné'),
date_to: z.string().min(1, 'Datum do je povinné'),
notes: z.string().nullish(),
});
export const ReviewLeaveRequestSchema = z.object({
status: z.string().min(1, 'Stav je povinný'),
reviewer_note: z.string().nullish(),
});
export type CreateLeaveRequestInput = z.infer<typeof CreateLeaveRequestSchema>;
export type ReviewLeaveRequestInput = z.infer<typeof ReviewLeaveRequestSchema>;

View File

@@ -0,0 +1,55 @@
import { z } from 'zod';
const QuotationItemSchema = z.object({
description: z.string().nullish(),
item_description: z.string().nullish(),
quantity: z.number().optional().default(1),
unit: z.string().nullish(),
unit_price: z.number().optional().default(0),
is_included_in_total: z.any().optional().default(true),
position: z.number().optional(),
});
const ScopeSectionSchema = z.object({
title: z.string().nullish(),
title_cz: z.string().nullish(),
content: z.string().nullish(),
position: z.number().optional(),
});
export const CreateQuotationSchema = z.object({
quotation_number: z.string().nullish(),
project_code: z.string().nullish(),
customer_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
valid_until: z.string().nullish(),
currency: z.string().optional().default('CZK'),
language: z.string().optional().default('cs'),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(21.0),
apply_vat: z.any().optional().default(true),
exchange_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(1.0),
status: z.string().optional().default('active'),
scope_title: z.string().nullish(),
scope_description: z.string().nullish(),
items: z.array(QuotationItemSchema).optional(),
sections: z.array(ScopeSectionSchema).optional(),
});
export const UpdateQuotationSchema = z.object({
quotation_number: z.string().optional(),
project_code: z.string().nullish(),
customer_id: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
valid_until: z.union([z.string(), z.null()]).optional(),
currency: z.string().optional(),
language: z.string().optional(),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
apply_vat: z.any().optional(),
exchange_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
status: z.string().optional(),
scope_title: z.string().nullish(),
scope_description: z.string().nullish(),
items: z.array(QuotationItemSchema).optional(),
sections: z.array(ScopeSectionSchema).optional(),
});
export type CreateQuotationInput = z.infer<typeof CreateQuotationSchema>;
export type UpdateQuotationInput = z.infer<typeof UpdateQuotationSchema>;

View File

@@ -0,0 +1,61 @@
import { z } from 'zod';
const OrderItemSchema = z.object({
description: z.string().nullish(),
item_description: z.string().nullish(),
quantity: z.number().optional().default(1),
unit: z.string().nullish(),
unit_price: z.number().optional().default(0),
is_included_in_total: z.any().optional().default(true),
position: z.number().optional(),
});
const OrderSectionSchema = z.object({
title: z.string().nullish(),
title_cz: z.string().nullish(),
content: z.string().nullish(),
position: z.number().optional(),
});
export const CreateOrderFromQuotationSchema = z.object({
quotationId: z.union([z.number(), z.string()]).transform(v => Number(v)),
customerOrderNumber: z.string().optional().default(''),
});
export const CreateOrderSchema = z.object({
order_number: z.string().nullish(),
customer_order_number: z.string().nullish(),
quotation_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
customer_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
status: z.string().optional().default('prijata'),
currency: z.string().optional().default('CZK'),
language: z.string().optional().default('cs'),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(21.0),
apply_vat: z.any().optional().default(true),
exchange_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(1.0),
scope_title: z.string().nullish(),
scope_description: z.string().nullish(),
notes: z.string().nullish(),
items: z.array(OrderItemSchema).optional(),
sections: z.array(OrderSectionSchema).optional(),
});
export const UpdateOrderSchema = z.object({
order_number: z.string().nullish(),
customer_order_number: z.string().nullish(),
status: z.string().optional(),
currency: z.string().optional(),
language: z.string().optional(),
scope_title: z.string().nullish(),
scope_description: z.string().nullish(),
notes: z.string().nullish(),
customer_id: z.union([z.number(), z.string(), z.null()]).optional(),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
apply_vat: z.any().optional(),
items: z.array(OrderItemSchema).optional(),
sections: z.array(OrderSectionSchema).optional(),
});
export type CreateOrderFromQuotationInput = z.infer<typeof CreateOrderFromQuotationSchema>;
export type CreateOrderInput = z.infer<typeof CreateOrderSchema>;
export type UpdateOrderInput = z.infer<typeof UpdateOrderSchema>;

View File

@@ -0,0 +1,11 @@
import { z } from 'zod';
export const UpdateProfileSchema = z.object({
email: z.string().email('Neplatný formát e-mailu').optional(),
first_name: z.string().optional(),
last_name: z.string().optional(),
current_password: z.string().optional(),
new_password: z.string().optional(),
});
export type UpdateProfileInput = z.infer<typeof UpdateProfileSchema>;

View File

@@ -0,0 +1,35 @@
import { z } from 'zod';
export const CreateProjectSchema = z.object({
project_number: z.string().nullish(),
name: z.string().nullish(),
customer_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
responsible_user_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
quotation_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
order_id: z.union([z.number(), z.string()]).transform(v => Number(v)).nullish(),
status: z.string().optional().default('aktivni'),
start_date: z.string().nullish(),
end_date: z.string().nullish(),
notes: z.string().nullish(),
});
export const UpdateProjectSchema = z.object({
project_number: z.string().nullish(),
name: z.string().nullish(),
status: z.string().optional(),
notes: z.string().nullish(),
customer_id: z.union([z.number(), z.string(), z.null()]).optional(),
responsible_user_id: z.union([z.number(), z.string(), z.null()]).optional(),
quotation_id: z.union([z.number(), z.string(), z.null()]).optional(),
order_id: z.union([z.number(), z.string(), z.null()]).optional(),
start_date: z.union([z.string(), z.null()]).optional(),
end_date: z.union([z.string(), z.null()]).optional(),
});
export const CreateProjectNoteSchema = z.object({
content: z.string().nullish(),
});
export type CreateProjectInput = z.infer<typeof CreateProjectSchema>;
export type UpdateProjectInput = z.infer<typeof UpdateProjectSchema>;
export type CreateProjectNoteInput = z.infer<typeof CreateProjectNoteSchema>;

View File

@@ -0,0 +1,37 @@
import { z } from 'zod';
export const CreateReceivedInvoiceSchema = z.object({
supplier_name: z.string().min(1, 'Název dodavatele je povinný'),
month: z.union([z.number(), z.string()]).transform(v => Number(v)),
year: z.union([z.number(), z.string()]).transform(v => Number(v)),
invoice_number: z.string().nullish(),
description: z.string().nullish(),
amount: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(0),
currency: z.string().optional().default('CZK'),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(21),
vat_amount: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(0),
issue_date: z.string().nullish(),
due_date: z.string().nullish(),
status: z.string().optional().default('unpaid'),
notes: z.string().nullish(),
});
export const UpdateReceivedInvoiceSchema = z.object({
supplier_name: z.string().optional(),
invoice_number: z.string().nullish(),
description: z.string().nullish(),
amount: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
currency: z.string().optional(),
vat_rate: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
vat_amount: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
issue_date: z.union([z.string(), z.null()]).optional(),
due_date: z.union([z.string(), z.null()]).optional(),
paid_date: z.union([z.string(), z.null()]).optional(),
status: z.string().optional(),
notes: z.string().nullish(),
month: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
year: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
});
export type CreateReceivedInvoiceInput = z.infer<typeof CreateReceivedInvoiceSchema>;
export type UpdateReceivedInvoiceInput = z.infer<typeof UpdateReceivedInvoiceSchema>;

View File

@@ -0,0 +1,17 @@
import { z } from 'zod';
export const CreateRoleSchema = z.object({
name: z.string().min(1, 'Název role je povinný'),
display_name: z.string().min(1, 'Zobrazovaný název je povinný'),
description: z.string().nullish(),
permission_ids: z.array(z.number()).optional(),
});
export const UpdateRoleSchema = z.object({
display_name: z.string().optional(),
description: z.string().optional(),
permission_ids: z.array(z.number()).optional(),
});
export type CreateRoleInput = z.infer<typeof CreateRoleSchema>;
export type UpdateRoleInput = z.infer<typeof UpdateRoleSchema>;

View File

@@ -0,0 +1,34 @@
import { z } from 'zod';
const ScopeSectionSchema = z.object({
title: z.string().nullish(),
title_cz: z.string().nullish(),
content: z.string().nullish(),
position: z.number().optional(),
});
export const CreateScopeTemplateSchema = z.object({
name: z.string().nullish(),
title: z.string().nullish(),
description: z.string().nullish(),
sections: z.array(ScopeSectionSchema).optional(),
});
export const CreateItemTemplateSchema = z.object({
id: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
name: z.string().nullish(),
description: z.string().nullish(),
default_price: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(0),
category: z.string().nullish(),
});
export const UpdateScopeTemplateSchema = z.object({
name: z.string().optional(),
title: z.string().optional(),
description: z.string().optional(),
sections: z.array(ScopeSectionSchema).optional(),
});
export type CreateScopeTemplateInput = z.infer<typeof CreateScopeTemplateSchema>;
export type CreateItemTemplateInput = z.infer<typeof CreateItemTemplateSchema>;
export type UpdateScopeTemplateInput = z.infer<typeof UpdateScopeTemplateSchema>;

View File

@@ -0,0 +1,26 @@
import { z } from 'zod';
export const CreateTripSchema = z.object({
vehicle_id: z.union([z.number(), z.string()]).transform(v => Number(v)),
user_id: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
trip_date: z.string(),
start_km: z.union([z.number(), z.string()]).transform(v => Number(v)),
end_km: z.union([z.number(), z.string()]).transform(v => Number(v)),
route_from: z.string(),
route_to: z.string(),
is_business: z.any().optional().default(false),
notes: z.string().nullish(),
});
export const UpdateTripSchema = z.object({
trip_date: z.string().optional(),
start_km: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
end_km: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
route_from: z.string().optional(),
route_to: z.string().optional(),
is_business: z.any().optional(),
notes: z.string().nullish(),
});
export type CreateTripInput = z.infer<typeof CreateTripSchema>;
export type UpdateTripInput = z.infer<typeof UpdateTripSchema>;

View File

@@ -0,0 +1,24 @@
import { z } from 'zod';
export const CreateUserSchema = z.object({
username: z.string().min(1, 'Uživatelské jméno je povinné'),
email: z.string().email('Neplatný formát e-mailu'),
password: z.string().min(8, 'Heslo musí mít alespoň 8 znaků'),
first_name: z.string().min(1, 'Jméno je povinné'),
last_name: z.string().min(1, 'Příjmení je povinné'),
role_id: z.union([z.number(), z.string()]).transform(v => Number(v)),
is_active: z.any().optional().default(true),
});
export const UpdateUserSchema = z.object({
username: z.string().optional(),
email: z.string().email('Neplatný formát e-mailu').optional(),
password: z.string().min(8, 'Heslo musí mít alespoň 8 znaků').optional(),
first_name: z.string().optional(),
last_name: z.string().optional(),
role_id: z.union([z.number(), z.string(), z.null()]).optional(),
is_active: z.any().optional(),
});
export type CreateUserInput = z.infer<typeof CreateUserSchema>;
export type UpdateUserInput = z.infer<typeof UpdateUserSchema>;

View File

@@ -0,0 +1,24 @@
import { z } from 'zod';
export const CreateVehicleSchema = z.object({
spz: z.string().min(1, 'SPZ je povinná'),
name: z.string().min(1, 'Název je povinný'),
brand: z.string().nullish(),
model: z.string().nullish(),
initial_km: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(0),
actual_km: z.union([z.number(), z.string()]).transform(v => Number(v)).optional().default(0),
is_active: z.any().optional().default(true),
});
export const UpdateVehicleSchema = z.object({
spz: z.string().optional(),
name: z.string().optional(),
brand: z.string().nullish(),
model: z.string().nullish(),
initial_km: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
actual_km: z.union([z.number(), z.string()]).transform(v => Number(v)).optional(),
is_active: z.any().optional(),
});
export type CreateVehicleInput = z.infer<typeof CreateVehicleSchema>;
export type UpdateVehicleInput = z.infer<typeof UpdateVehicleSchema>;