mirror of
https://github.com/Since-3/since3-portal.git
synced 2026-10-12 20:51:17 +00:00
68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
import * as z from "zod";
|
|
|
|
export const INVOICE_STATUSES = ["pending", "paid", "cancelled"] as const;
|
|
export type InvoiceStatus = (typeof INVOICE_STATUSES)[number];
|
|
|
|
const isoDate = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, { error: "Ungültiges Datum." });
|
|
|
|
export const InvoiceItemSchema = z.object({
|
|
productTemplateId: z.string().uuid().nullable(),
|
|
description: z.string().trim().min(1, { error: "Jede Position braucht eine Bezeichnung." }),
|
|
quantity: z.number().positive({ error: "Menge muss größer als 0 sein." }),
|
|
unitPrice: z.number().min(0, { error: "Preis darf nicht negativ sein." }),
|
|
taxRate: z.number().min(0).max(100),
|
|
});
|
|
|
|
export const InvoiceDraftSchema = z
|
|
.object({
|
|
profileId: z.string().uuid(),
|
|
companyName: z.string().trim().min(1, { error: "Firmenname ist erforderlich." }),
|
|
billingStreet: z.string().trim().min(1, { error: "Straße ist erforderlich." }),
|
|
billingPostalCode: z.string().trim().min(1, { error: "PLZ ist erforderlich." }),
|
|
billingCity: z.string().trim().min(1, { error: "Stadt ist erforderlich." }),
|
|
billingCountry: z.string().trim().length(2, { error: "Land muss ein 2-stelliger Code sein." }),
|
|
invoiceDate: isoDate,
|
|
dueDate: isoDate,
|
|
items: z.array(InvoiceItemSchema).min(1, { error: "Mindestens eine Position hinzufügen." }),
|
|
})
|
|
.refine((data) => data.dueDate >= data.invoiceDate, {
|
|
path: ["dueDate"],
|
|
error: "Fälligkeit darf nicht vor dem Rechnungsdatum liegen.",
|
|
});
|
|
|
|
export type InvoiceItemDraft = z.infer<typeof InvoiceItemSchema>;
|
|
export type InvoiceDraft = z.infer<typeof InvoiceDraftSchema>;
|
|
|
|
export type InvoicePdfData = {
|
|
invoiceNumber: string;
|
|
invoiceDate: string;
|
|
dueDate: string;
|
|
companyName: string;
|
|
billingStreet: string;
|
|
billingPostalCode: string;
|
|
billingCity: string;
|
|
billingCountry: string;
|
|
items: { description: string; quantity: number; unitPrice: number; taxRate: number }[];
|
|
};
|
|
|
|
export type InvoiceListItem = {
|
|
id: string;
|
|
invoiceNumber: string;
|
|
status: InvoiceStatus;
|
|
displayStatus: InvoiceStatus | "overdue";
|
|
grossTotal: number;
|
|
dueDate: string;
|
|
invoiceDate: string;
|
|
};
|
|
|
|
export type ProductTemplate = {
|
|
id: string;
|
|
name: string;
|
|
description: string | null;
|
|
unitPrice: number;
|
|
taxRate: number;
|
|
};
|
|
|
|
export function firstIssueMessage(error: z.ZodError) {
|
|
return error.issues[0]?.message ?? "Bitte alle Pflichtfelder ausfüllen.";
|
|
}
|