Files
app/src/schemas/issued-orders.schema.ts
BOHA fb480d886d fix(documents): gate selected_custom_fields behind editable guard; bound index cap to column width
Addresses review: add selected_custom_fields to offers/issued-orders
NON_STATUS_UPDATE_FIELDS so a non-editable document rejects selection
edits (status-only transitions still pass); tighten Zod cap 200->50 to
stay within VARCHAR(255).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 20:31:58 +02:00

58 lines
2.1 KiB
TypeScript

import { z } from "zod";
import {
nonNegativeNumberFromForm,
positiveNumberFromForm,
nullableIntIdFromForm,
isoDateString,
DocumentSectionSchema,
} from "./common";
export const IssuedOrderItemSchema = z.object({
description: z.string().max(500).nullish(),
item_description: z.string().max(5000).nullish(),
quantity: positiveNumberFromForm.optional(),
unit: z.string().max(20).nullish(),
unit_price: nonNegativeNumberFromForm.optional(),
position: z.number().int().nonnegative().optional(),
});
const ISSUED_ORDER_STATUSES = [
"draft",
"sent",
"confirmed",
"completed",
"cancelled",
] as const;
export const CreateIssuedOrderSchema = z.object({
po_number: z.string().max(50).nullish(),
supplier_id: nullableIntIdFromForm.nullish(),
status: z.enum(ISSUED_ORDER_STATUSES).optional(),
currency: z.string().max(10).optional(),
exchange_rate: nonNegativeNumberFromForm.optional(),
order_date: isoDateString.nullish(),
delivery_date: isoDateString.nullish(),
language: z.string().max(5).optional(),
// Editable heading above the PDF items table; empty/null falls back to the
// default "Objednáváme si u Vás:" (issued-orders-pdf t.billing).
order_text: z.string().max(500).nullish(),
internal_notes: z.string().nullish(),
items: z.array(IssuedOrderItemSchema).optional(),
// Rich-text CZ/EN sections rendered on their own PDF page (mirrors offers'
// scope_sections — shared DocumentSectionSchema, DB-aligned limits).
sections: z.array(DocumentSectionSchema).optional(),
// Positional indices of company custom fields to print on this document's
// PDF. Omitted/empty ⇒ none. Update schema derives via .partial().
selected_custom_fields: z
.array(z.number().int().nonnegative())
.max(50)
.optional(),
});
// Update = partial create MINUS the number: PO numbers are immutable
// (assigned by the sequence on finalize), so the field is stripped before it
// can ever reach the service (which never reads it on update anyway).
export const UpdateIssuedOrderSchema = CreateIssuedOrderSchema.partial().omit({
po_number: true,
});