import { z } from 'zod'; import { uuidSchema, moneySchema, paginationSchema, } from '../../../shared/validation/common.schema'; // Enums export const movementTypeEnum = z.enum([ 'cash_in', 'cash_out', 'deposit', 'withdrawal', 'adjustment', 'opening', 'closing', ]); export const movementReasonEnum = z.enum([ 'change_fund', 'petty_cash', 'bank_deposit', 'supplier_payment', 'expense', 'salary_advance', 'correction', 'other', ]); export const movementStatusEnum = z.enum([ 'pending', 'approved', 'rejected', 'cancelled', ]); export const closingTypeEnum = z.enum(['shift', 'daily', 'weekly', 'monthly']); export const closingStatusEnum = z.enum([ 'in_progress', 'pending_review', 'approved', 'rejected', 'reconciled', ]); export const denominationTypeEnum = z.enum(['bill', 'coin']); // ==================== MOVEMENT SCHEMAS ==================== // Create movement schema export const createMovementSchema = z.object({ branchId: uuidSchema, registerId: uuidSchema, sessionId: uuidSchema, type: movementTypeEnum, reason: movementReasonEnum.optional(), amount: moneySchema.positive('Amount must be positive'), description: z.string().min(1, 'Description is required').max(500), referenceType: z.string().max(50).optional(), referenceId: uuidSchema.optional(), referenceNumber: z.string().max(50).optional(), requiresApproval: z.boolean().optional(), recipientName: z.string().max(200).optional(), recipientId: uuidSchema.optional(), accountId: uuidSchema.optional(), bankAccount: z.string().max(50).optional(), depositSlipNumber: z.string().max(50).optional(), notes: z.string().max(1000).optional(), metadata: z.record(z.any()).optional(), }); // Approve/reject movement schema export const movementActionSchema = z.object({ reason: z.string().max(255).optional(), }); // List movements query schema export const listMovementsQuerySchema = paginationSchema.extend({ branchId: uuidSchema.optional(), sessionId: uuidSchema.optional(), registerId: uuidSchema.optional(), type: movementTypeEnum.optional(), reason: movementReasonEnum.optional(), status: movementStatusEnum.optional(), startDate: z.coerce.date().optional(), endDate: z.coerce.date().optional(), }); // ==================== CLOSING SCHEMAS ==================== // Create closing schema export const createClosingSchema = z.object({ branchId: uuidSchema, registerId: uuidSchema.optional(), sessionId: uuidSchema.optional(), type: closingTypeEnum, periodStart: z.coerce.date(), periodEnd: z.coerce.date(), openingBalance: moneySchema.default(0), closingNotes: z.string().max(1000).optional(), }).refine(data => data.periodStart <= data.periodEnd, { message: 'Period start must be before or equal to period end', path: ['periodEnd'], }); // Denomination count schema export const denominationCountSchema = z.object({ type: denominationTypeEnum, denomination: z.number().positive(), quantity: z.number().int().min(0), }); // Submit cash count schema export const submitCashCountSchema = z.object({ denominations: z.array(denominationCountSchema).min(1, 'At least one denomination is required'), }); // Submit payment counts schema export const submitPaymentCountsSchema = z.object({ cash: moneySchema.optional(), card: moneySchema.default(0), transfer: moneySchema.default(0), other: moneySchema.default(0), }); // Closing action schema (approve/reject) export const closingActionSchema = z.object({ notes: z.string().max(1000).optional(), }); // Reject closing schema (requires notes) export const rejectClosingSchema = z.object({ notes: z.string().min(1, 'Rejection reason is required').max(1000), }); // Reconcile closing schema export const reconcileClosingSchema = z.object({ depositAmount: moneySchema.positive('Deposit amount must be positive'), depositReference: z.string().min(1).max(100), depositDate: z.coerce.date(), }); // List closings query schema export const listClosingsQuerySchema = paginationSchema.extend({ branchId: uuidSchema.optional(), sessionId: uuidSchema.optional(), status: closingStatusEnum.optional(), type: closingTypeEnum.optional(), startDate: z.coerce.date().optional(), endDate: z.coerce.date().optional(), }); // Types export type CreateMovementInput = z.infer; export type ListMovementsQuery = z.infer; export type CreateClosingInput = z.infer; export type SubmitCashCountInput = z.infer; export type SubmitPaymentCountsInput = z.infer; export type ReconcileClosingInput = z.infer; export type ListClosingsQuery = z.infer;