import { z } from "zod"; import { numberFromForm, numberInRange, nonNegativeNumberFromForm, positiveNumberFromForm, nullableIntIdFromForm, booleanFromForm, nullableIsoDateString, DocumentSectionSchema, } from "./common"; const InvoiceItemSchema = z.object({ description: z.string().max(500).nullish(), item_description: z.string().max(8000).nullish(), quantity: positiveNumberFromForm.default(1), unit: z.string().max(20).nullish(), unit_price: numberFromForm.default(0), // Per-item discount as a percentage (0–100); column is Decimal(5,2). discount: numberInRange(0, 100).optional().default(0), vat_rate: numberInRange(0, 100).optional().default(21.0), position: nonNegativeNumberFromForm.optional(), }); export const CreateInvoiceSchema = z.object({ invoice_number: z.string().max(50).nullish(), order_id: nullableIntIdFromForm.nullish(), customer_id: nullableIntIdFromForm.nullish(), status: z.string().max(20).optional().default("draft"), currency: z.string().max(10).optional().default("CZK"), vat_rate: numberInRange(0, 100).optional().default(21.0), apply_vat: booleanFromForm.optional().default(true), payment_method: z.string().max(50).nullish(), constant_symbol: z.string().max(20).nullish(), bank_name: z.string().max(255).nullish(), bank_swift: z.string().max(20).nullish(), bank_iban: z.string().max(50).nullish(), bank_account: z.string().max(50).nullish(), issue_date: nullableIsoDateString, due_date: nullableIsoDateString, tax_date: nullableIsoDateString, issued_by: z.string().max(255).nullish(), billing_text: z.string().max(500).nullish(), language: z.string().max(5).optional().default("cs"), // `notes` was dropped (printed-notes block removed — free-form PDF content // lives in the sections); legacy clients still sending it are silently // stripped by z.object. internal_notes is never printed. internal_notes: z.string().max(8000).nullish(), items: z.array(InvoiceItemSchema).optional(), // Rich-text CZ/EN "Obsah" sections rendered after the items on the PDF // (mirrors issued orders — shared DocumentSectionSchema, DB-aligned limits). sections: z.array(DocumentSectionSchema).optional(), // Positional indices of company custom fields to print on this document's PDF. selected_custom_fields: z .array(z.number().int().nonnegative()) .max(200) .optional(), }); export const UpdateInvoiceSchema = z.object({ status: z.string().max(20).optional(), currency: z.string().max(10).optional(), language: z.string().max(5).optional(), payment_method: z.string().max(50).nullish(), constant_symbol: z.string().max(20).nullish(), bank_name: z.string().max(255).nullish(), bank_swift: z.string().max(20).nullish(), bank_iban: z.string().max(50).nullish(), bank_account: z.string().max(50).nullish(), issued_by: z.string().max(255).nullish(), billing_text: z.string().max(500).nullish(), customer_id: nullableIntIdFromForm.optional(), vat_rate: numberInRange(0, 100).optional(), apply_vat: booleanFromForm.optional(), issue_date: nullableIsoDateString, due_date: nullableIsoDateString, tax_date: nullableIsoDateString, internal_notes: z.string().max(8000).nullish(), paid_date: nullableIsoDateString, items: z.array(InvoiceItemSchema).optional(), sections: z.array(DocumentSectionSchema).optional(), selected_custom_fields: z .array(z.number().int().nonnegative()) .max(200) .optional(), }); export type CreateInvoiceInput = z.infer; export type UpdateInvoiceInput = z.infer;