/** * TypeScript types for the payroll module. */ // ── Payroll Run ────────────────────────────────────────────── export type PayrollRunStatus = "draft" | "confirmed" | "processed"; export interface PayrollRun { id: string; organisation_id: string; period_start: string; period_end: string; pay_frequency: "weekly" | "fortnightly" | "monthly"; status: PayrollRunStatus; jurisdiction_country_code: string; jurisdiction_name: string; total_gross: number; total_deductions: number; total_net: number; total_employer_contributions: number; confirmed_by: string | null; confirmed_at: string | null; created_by: string | null; created_at: string; } // ── Payslip ────────────────────────────────────────────────── export interface PayslipLineItem { name: string; amount: number; type?: string; description?: string; } export interface Payslip { id: string; payroll_run_id: string; employee_id: string; organisation_id: string; gross_pay: number; total_deductions: number; net_pay: number; employer_contributions: number; deduction_lines: PayslipLineItem[]; employer_contribution_lines: PayslipLineItem[]; hours_worked: number | null; hourly_rate: number | null; created_at: string; } export interface PayslipWithEmployee extends Payslip { employee: { id: string; first_name: string; last_name: string; email: string; job_title: string | null; }; } // ── Payroll Run Summary (for list view) ────────────────────── export interface PayrollRunSummary { id: string; period_start: string; period_end: string; pay_frequency: "weekly" | "fortnightly" | "monthly"; status: PayrollRunStatus; jurisdiction_name: string; jurisdiction_country_code: string; total_gross: number; total_net: number; employee_count: number; created_at: string; } // ── Employee Payroll Preview (for new run) ─────────────────── export interface EmployeePayrollPreview { employee_id: string; first_name: string; last_name: string; email: string; job_title: string | null; employment_type: string; annual_salary: number | null; hourly_rate: number | null; hours_worked: number; gross_pay: number; deductions: PayslipLineItem[]; total_deductions: number; net_pay: number; employer_contributions: PayslipLineItem[]; total_employer_contributions: number; } // ── Create Payroll Run Input ───────────────────────────────── export interface CreatePayrollRunInput { period_start: string; period_end: string; pay_frequency: "weekly" | "fortnightly" | "monthly"; employees: { employee_id: string; hours_worked?: number; }[]; } // ── Helpers ────────────────────────────────────────────────── export const STATUS_LABELS: Record = { draft: "Draft", confirmed: "Confirmed", processed: "Processed", }; export const STATUS_COLORS: Record = { draft: "bg-gray-100 text-gray-600 border-gray-200", confirmed: "bg-blue-100 text-blue-700 border-blue-200", processed: "bg-emerald-100 text-emerald-700 border-emerald-200", }; export function formatCurrency(amount: number, currency = "USD"): string { const symbols: Record = { USD: "$", AUD: "A$", GBP: "£", CAD: "C$", NZD: "NZ$", EUR: "€", INR: "₹", SGD: "S$", JPY: "¥", }; const sym = symbols[currency] || "$"; return `${sym}${amount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; } export function formatDateShort(dateStr: string): string { return new Date(dateStr + "T00:00:00").toLocaleDateString("en-AU", { day: "numeric", month: "short", year: "numeric", }); }