export type ExpenseType = 'VendorPayment' | 'StaffReimbursement'; export type ExpenseStatus = 'Draft' | 'PendingApproval' | 'Approved' | 'Paid' | 'Rejected'; export type FunctionalClass = 'Program' | 'ManagementGeneral' | 'Fundraising'; export interface PagedResult { items: T[]; totalCount: number; page: number; pageSize: number; totalPages: number; } export interface MinistryDto { id: number; name_en: string; name_zh: string | null; sortOrder: number; isActive: boolean; label?: string; } export interface ExpenseSubCategoryDto { id: number; groupId: number; name_en: string; name_zh: string | null; sortOrder: number; isActive: boolean; label?: string; form990LineId: number | null; form990LineCode: string | null; } export interface ExpenseCategoryGroupDto { id: number; name_en: string; name_zh: string | null; sortOrder: number; isActive: boolean; subCategories: ExpenseSubCategoryDto[]; label?: string; form990LineId: number | null; form990LineCode: string | null; } export interface CreateExpenseGroupRequest { name_en: string; name_zh: string | null; sortOrder: number; form990LineId: number | null; } export interface UpdateExpenseGroupRequest extends CreateExpenseGroupRequest { isActive: boolean; } export interface CreateExpenseSubCategoryRequest { groupId: number; name_en: string; name_zh: string | null; sortOrder: number; form990LineId: number | null; } export interface UpdateExpenseSubCategoryRequest extends CreateExpenseSubCategoryRequest { isActive: boolean; } export interface ExpenseLineItemDto { id: number; categoryGroupId: number; categoryGroupName: string; subCategoryId: number; subCategoryName: string; functionalClass: FunctionalClass | null; amount: number; description: string | null; } export interface ExpenseListItemDto { id: number; type: ExpenseType; status: ExpenseStatus; amount: number; description: string; ministryId: number; ministryName: string; lineCount: number; primaryCategoryName: string; vendorName: string | null; memberId: number | null; memberName: string | null; expenseDate: string; hasReceipt: boolean; checkNumber: string | null; reviewedByName: string | null; reviewedAt: string | null; reviewNotes: string | null; } export interface ExpenseDto extends ExpenseListItemDto { notes: string | null; submittedBy: string | null; submittedAt: string | null; paidAt: string | null; lines: ExpenseLineItemDto[]; } /** AI assist suggestion: English translation + a proposed major/sub category (null when unclassified). */ export interface ExpenseAiSuggestion { englishDescription: string | null; chineseDescription: string | null; groupId: number | null; subCategoryId: number | null; groupLabel: string | null; subLabel: string | null; confidence: number; } export interface ExpenseLineInput { categoryGroupId: number; subCategoryId: number; amount: number; functionalClass: FunctionalClass | null; description: string | null; } export interface CreateExpenseRequest { type: ExpenseType; ministryId: number; lines: ExpenseLineInput[]; description: string; vendorName: string | null; memberId: number | null; checkNumber: string | null; expenseDate: string; notes: string | null; } export type UpdateExpenseRequest = CreateExpenseRequest; export interface RejectExpenseRequest { reviewNotes: string | null; } export interface PayExpenseRequest { checkNumber: string | null; paidAt: string | null; } export interface MonthlyStatementDto { id: number; year: number; month: number; openingBalance: number; totalGiving: number; totalOtherIncome: number; totalExpenses: number; calculatedClosingBalance: number; bankStatementBalance: number; difference: number; notes: string | null; isFinalized: boolean; } export interface CreateMonthlyStatementRequest { year: number; month: number; openingBalance: number; totalOtherIncome: number; bankStatementBalance: number; notes: string | null; } export interface UpdateMonthlyStatementRequest { openingBalance: number; totalOtherIncome: number; bankStatementBalance: number; notes: string | null; }