2025-10-03 14:26:55 +09:00
|
|
|
/**
|
|
|
|
|
* Billing Domain - Schemas
|
|
|
|
|
*
|
|
|
|
|
* Zod validation schemas for billing domain types.
|
|
|
|
|
* Used for runtime validation of data from any source.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { z } from "zod";
|
|
|
|
|
|
|
|
|
|
// Invoice Status Schema
|
|
|
|
|
export const invoiceStatusSchema = z.enum([
|
|
|
|
|
"Draft",
|
|
|
|
|
"Pending",
|
|
|
|
|
"Paid",
|
|
|
|
|
"Unpaid",
|
|
|
|
|
"Overdue",
|
|
|
|
|
"Cancelled",
|
|
|
|
|
"Refunded",
|
|
|
|
|
"Collections",
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// Invoice Item Schema
|
|
|
|
|
export const invoiceItemSchema = z.object({
|
|
|
|
|
id: z.number().int().positive("Invoice item id must be positive"),
|
|
|
|
|
description: z.string().min(1, "Description is required"),
|
|
|
|
|
amount: z.number(),
|
|
|
|
|
quantity: z.number().int().positive("Quantity must be positive").optional(),
|
|
|
|
|
type: z.string().min(1, "Item type is required"),
|
|
|
|
|
serviceId: z.number().int().positive().optional(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Invoice Schema
|
|
|
|
|
export const invoiceSchema = z.object({
|
|
|
|
|
id: z.number().int().positive("Invoice id must be positive"),
|
|
|
|
|
number: z.string().min(1, "Invoice number is required"),
|
|
|
|
|
status: invoiceStatusSchema,
|
|
|
|
|
currency: z.string().min(1, "Currency is required"),
|
|
|
|
|
currencySymbol: z.string().min(1, "Currency symbol is required").optional(),
|
|
|
|
|
total: z.number(),
|
|
|
|
|
subtotal: z.number(),
|
|
|
|
|
tax: z.number(),
|
|
|
|
|
issuedAt: z.string().optional(),
|
|
|
|
|
dueDate: z.string().optional(),
|
|
|
|
|
paidDate: z.string().optional(),
|
|
|
|
|
pdfUrl: z.string().optional(),
|
|
|
|
|
paymentUrl: z.string().optional(),
|
|
|
|
|
description: z.string().optional(),
|
|
|
|
|
items: z.array(invoiceItemSchema).optional(),
|
|
|
|
|
daysOverdue: z.number().int().nonnegative().optional(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Invoice Pagination Schema
|
|
|
|
|
export const invoicePaginationSchema = z.object({
|
|
|
|
|
page: z.number().int().nonnegative(),
|
|
|
|
|
totalPages: z.number().int().nonnegative(),
|
|
|
|
|
totalItems: z.number().int().nonnegative(),
|
|
|
|
|
nextCursor: z.string().optional(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Invoice List Schema
|
|
|
|
|
export const invoiceListSchema = z.object({
|
|
|
|
|
invoices: z.array(invoiceSchema),
|
|
|
|
|
pagination: invoicePaginationSchema,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Invoice SSO Link Schema
|
|
|
|
|
export const invoiceSsoLinkSchema = z.object({
|
|
|
|
|
url: z.string().url(),
|
|
|
|
|
expiresAt: z.string(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Payment Invoice Request Schema
|
|
|
|
|
export const paymentInvoiceRequestSchema = z.object({
|
|
|
|
|
invoiceId: z.number().int().positive(),
|
|
|
|
|
paymentMethodId: z.number().int().positive().optional(),
|
|
|
|
|
gatewayName: z.string().optional(),
|
|
|
|
|
amount: z.number().positive().optional(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Billing Summary Schema
|
|
|
|
|
export const billingSummarySchema = z.object({
|
|
|
|
|
totalOutstanding: z.number(),
|
|
|
|
|
totalOverdue: z.number(),
|
|
|
|
|
totalPaid: z.number(),
|
|
|
|
|
currency: z.string(),
|
|
|
|
|
currencySymbol: z.string().optional(),
|
|
|
|
|
invoiceCount: z.object({
|
|
|
|
|
total: z.number().int().min(0),
|
|
|
|
|
unpaid: z.number().int().min(0),
|
|
|
|
|
overdue: z.number().int().min(0),
|
|
|
|
|
paid: z.number().int().min(0),
|
|
|
|
|
}),
|
|
|
|
|
});
|
2025-10-07 17:38:39 +09:00
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Query Parameter Schemas
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Schema for invoice list query parameters
|
|
|
|
|
*/
|
|
|
|
|
export const invoiceQueryParamsSchema = z.object({
|
|
|
|
|
page: z.coerce.number().int().positive().optional(),
|
|
|
|
|
limit: z.coerce.number().int().positive().max(100).optional(),
|
|
|
|
|
status: invoiceStatusSchema.optional(),
|
|
|
|
|
dateFrom: z.string().datetime().optional(),
|
|
|
|
|
dateTo: z.string().datetime().optional(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export type InvoiceQueryParams = z.infer<typeof invoiceQueryParamsSchema>;
|
2025-10-08 10:33:33 +09:00
|
|
|
|
|
|
|
|
const invoiceListStatusSchema = z.enum(["Paid", "Unpaid", "Cancelled", "Overdue", "Collections"]);
|
|
|
|
|
|
|
|
|
|
export const invoiceListQuerySchema = z.object({
|
|
|
|
|
page: z.coerce.number().int().positive().optional(),
|
|
|
|
|
limit: z.coerce.number().int().positive().max(100).optional(),
|
|
|
|
|
status: invoiceListStatusSchema.optional(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export type InvoiceListQuery = z.infer<typeof invoiceListQuerySchema>;
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
// Inferred Types from Schemas (Schema-First Approach)
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
export type InvoiceStatus = z.infer<typeof invoiceStatusSchema>;
|
|
|
|
|
export type InvoiceItem = z.infer<typeof invoiceItemSchema>;
|
|
|
|
|
export type Invoice = z.infer<typeof invoiceSchema>;
|
|
|
|
|
export type InvoicePagination = z.infer<typeof invoicePaginationSchema>;
|
|
|
|
|
export type InvoiceList = z.infer<typeof invoiceListSchema>;
|
|
|
|
|
export type InvoiceSsoLink = z.infer<typeof invoiceSsoLinkSchema>;
|
|
|
|
|
export type PaymentInvoiceRequest = z.infer<typeof paymentInvoiceRequestSchema>;
|
|
|
|
|
export type BillingSummary = z.infer<typeof billingSummarySchema>;
|