86 lines
2.8 KiB
TypeScript
86 lines
2.8 KiB
TypeScript
import { z } from "zod"
|
|
import { BillStatus, DiscountType } from "@garage/api"
|
|
|
|
const relationFieldSchema = z
|
|
.object({ value: z.string(), label: z.string() })
|
|
.nullable()
|
|
|
|
const optionalDateSchema = z.preprocess(
|
|
(value) => (value === "" || value == null ? undefined : value),
|
|
z.string().date().optional(),
|
|
)
|
|
|
|
const optionalStringMax255Schema = z.preprocess(
|
|
(value) => (value === "" || value == null ? undefined : value),
|
|
z.string().max(255, "Must be at most 255 characters").optional(),
|
|
)
|
|
|
|
const requiredDateSchema = z
|
|
.string()
|
|
.min(1, "Bill date is required")
|
|
.date("Enter a valid date")
|
|
|
|
const billPartItemSchema = z.object({
|
|
part_id: z.number(),
|
|
title: z.string(),
|
|
quantity: z.number().min(1),
|
|
rate: z.number().min(0),
|
|
discount_amount: z.number().min(0).optional(),
|
|
description: z.string().optional(),
|
|
})
|
|
|
|
const billServiceItemSchema = z.object({
|
|
service_id: z.number(),
|
|
title: z.string(),
|
|
quantity: z.number().min(1),
|
|
rate: z.number().min(0),
|
|
discount_amount: z.number().min(0).optional(),
|
|
description: z.string().optional(),
|
|
})
|
|
|
|
const billExpenseItemSchema = z.object({
|
|
expense_id: z.number(),
|
|
title: z.string(),
|
|
quantity: z.number().min(1),
|
|
rate: z.number().min(0),
|
|
discount_amount: z.number().min(0).optional(),
|
|
description: z.string().optional(),
|
|
})
|
|
|
|
const billFormSchema = z.object({
|
|
// ── Required ──
|
|
title: z.string().trim().min(1, "Title is required").max(255, "Title must be at most 255 characters"),
|
|
|
|
// ── Relations ──
|
|
vendor: relationFieldSchema,
|
|
vendor_address: relationFieldSchema,
|
|
purchase_order: relationFieldSchema,
|
|
job_card: relationFieldSchema,
|
|
payment_term: relationFieldSchema,
|
|
department: relationFieldSchema,
|
|
tax: relationFieldSchema,
|
|
|
|
// ── Optional fields ──
|
|
bill_number: optionalStringMax255Schema,
|
|
bill_date: requiredDateSchema,
|
|
bill_due_date: optionalDateSchema,
|
|
status: z.enum(BillStatus).optional(),
|
|
discount: z.enum(DiscountType).optional(),
|
|
discount_amount: z.coerce.number().min(0).optional(),
|
|
notes: z.string().optional(),
|
|
label_ids: z.array(z.number()).optional(),
|
|
|
|
// ── Line items ──
|
|
part_items: z.array(billPartItemSchema).optional(),
|
|
service_items: z.array(billServiceItemSchema).optional(),
|
|
expense_items: z.array(billExpenseItemSchema).optional(),
|
|
})
|
|
|
|
type BillFormValues = z.infer<typeof billFormSchema>
|
|
type BillPartItem = z.infer<typeof billPartItemSchema>
|
|
type BillServiceItem = z.infer<typeof billServiceItemSchema>
|
|
type BillExpenseItem = z.infer<typeof billExpenseItemSchema>
|
|
|
|
export { billFormSchema, relationFieldSchema, billPartItemSchema, billServiceItemSchema, billExpenseItemSchema }
|
|
export type { BillFormValues, BillPartItem, BillServiceItem, BillExpenseItem }
|