@@ -63,7 +63,7 @@ const DEFAULT_VALUES: PaymentMadeFormValues & { details: Array<{ bill_id?: strin
|
||||
payment_date: getTodayDate(),
|
||||
paid_through: "",
|
||||
notes: "",
|
||||
details: []
|
||||
details: [{ amount_paid: 0 }]
|
||||
}
|
||||
|
||||
// ── Mapping helpers ──
|
||||
@@ -79,14 +79,14 @@ function mapToFormValues(data: unknown): typeof DEFAULT_VALUES {
|
||||
vendor: toRelation(d.vendor_id, d.vendor?.company_name ?? d.vendor?.name ?? d.vendor_name),
|
||||
employee: toRelation(d.employee_id, d.employee?.first_name ? `${d.employee.first_name} ${d.employee.last_name ?? ""}`.trim() : d.employee_name),
|
||||
payment_mode: toRelation(paymentModeId, paymentModeLabel),
|
||||
payment_for: d.payment_for || "",
|
||||
payment_for: d.payment_for || "bill",
|
||||
amount: d.payment_made ? String(d.payment_made) : "",
|
||||
payment_number: d.payment_number || "",
|
||||
payment_reference: d.payment_reference || "",
|
||||
payment_date: d.payment_date || "",
|
||||
paid_through: d.paid_through || "-",
|
||||
notes: d.notes || "-",
|
||||
details: [{ bill_id: d.bill_id, amount_paid: d.amount_paid }],
|
||||
details: [{ bill_id: d.bill_id, expense_id: d.expense_id, amount_paid: d.amount_paid ?? 0 }],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,6 +249,7 @@ export function PaymentMadeForm({ resourceId, initialData, onSuccess, billId, ex
|
||||
name="payment_mode"
|
||||
label="Payment Mode"
|
||||
placeholder="Select payment mode"
|
||||
required
|
||||
queryKey={[PAYMENT_MODE_ROUTES.INDEX]}
|
||||
listFn={() => api.paymentModes.list()}
|
||||
mapOption={mapLookupOption}
|
||||
|
||||
@@ -1,23 +1,61 @@
|
||||
import { z } from "zod"
|
||||
import { PaymentFor } from "@garage/api"
|
||||
|
||||
const relationFieldSchema = z
|
||||
.object({ value: z.string(), label: z.string() })
|
||||
.nullable()
|
||||
|
||||
const requiredRelationFieldSchema = relationFieldSchema.superRefine((value, ctx) => {
|
||||
if (!value?.value) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "This field is required",
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const optionalStringMax255Schema = z.preprocess(
|
||||
(value) => (value === "" || value == null ? undefined : value),
|
||||
z.string().max(255, "Must be at most 255 characters").optional(),
|
||||
)
|
||||
|
||||
const detailsItemSchema = z.object({
|
||||
bill_id: z.union([z.string(), z.number()]).optional().nullable(),
|
||||
expense_id: z.union([z.string(), z.number()]).optional().nullable(),
|
||||
amount_paid: z.coerce.number().min(0).optional(),
|
||||
})
|
||||
|
||||
const paymentMadeFormSchema = z.object({
|
||||
// ── Relations ──
|
||||
vendor: relationFieldSchema,
|
||||
employee: relationFieldSchema,
|
||||
payment_mode: relationFieldSchema,
|
||||
payment_mode: requiredRelationFieldSchema,
|
||||
|
||||
// ── Payment info ──
|
||||
amount: z.string().min(1, "Amount is required"),
|
||||
payment_for: z.string().min(1, "Payment for is required"),
|
||||
payment_number: z.string().optional(),
|
||||
payment_reference: z.string().optional(),
|
||||
payment_date: z.string().min(1, "Payment date is required"),
|
||||
paid_through: z.string().optional(),
|
||||
amount: z.coerce.number().min(0, "Amount must be 0 or more"),
|
||||
payment_for: z.enum(PaymentFor),
|
||||
payment_number: optionalStringMax255Schema,
|
||||
payment_reference: optionalStringMax255Schema,
|
||||
payment_date: z.string().min(1, "Payment date is required").date("Enter a valid date"),
|
||||
paid_through: optionalStringMax255Schema,
|
||||
notes: z.string().optional(),
|
||||
details: z.array(detailsItemSchema).min(1, "At least one payment detail is required"),
|
||||
}).superRefine((values, ctx) => {
|
||||
const hasVendor = Boolean(values.vendor?.value)
|
||||
const hasEmployee = Boolean(values.employee?.value)
|
||||
|
||||
if (!hasVendor && !hasEmployee) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["vendor"],
|
||||
message: "Vendor or employee is required",
|
||||
})
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["employee"],
|
||||
message: "Vendor or employee is required",
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
type PaymentMadeFormValues = z.infer<typeof paymentMadeFormSchema>
|
||||
|
||||
Reference in New Issue
Block a user