189 行
4.2 KiB
TypeScript
189 行
4.2 KiB
TypeScript
import { apiRequestData } from "./http";
|
|
|
|
export type SalaryItemType = "earning" | "deduction";
|
|
export type PayslipStatus = "draft" | "issued";
|
|
|
|
export type SalaryItem = {
|
|
id: string;
|
|
name: string;
|
|
itemType: SalaryItemType;
|
|
sortOrder: number;
|
|
enabled: boolean;
|
|
createdAt: string | null;
|
|
createdBy: string | null;
|
|
updatedAt: string | null;
|
|
updatedBy: string | null;
|
|
};
|
|
|
|
export type EmployeeSalaryProfileItem = {
|
|
salaryItemId: string;
|
|
name: string;
|
|
itemType: SalaryItemType;
|
|
sortOrder: number;
|
|
monthlyAmount: number;
|
|
};
|
|
|
|
export type EmployeeSalaryProfileSnapshot = {
|
|
effectiveDate: string;
|
|
createdAt: string | null;
|
|
createdBy: string | null;
|
|
updatedAt: string | null;
|
|
updatedBy: string | null;
|
|
items: EmployeeSalaryProfileItem[];
|
|
};
|
|
|
|
export type PayslipItem = {
|
|
salaryItemId: string;
|
|
name: string;
|
|
itemType: SalaryItemType;
|
|
sortOrder: number;
|
|
amount: number;
|
|
};
|
|
|
|
export type Payslip = {
|
|
id: string;
|
|
employeeId: string;
|
|
payMonth: string | null;
|
|
status: PayslipStatus;
|
|
grossAmount: number;
|
|
deductionAmount: number;
|
|
netAmount: number;
|
|
issuedAt: string | null;
|
|
createdAt: string | null;
|
|
createdBy: string | null;
|
|
updatedAt: string | null;
|
|
updatedBy: string | null;
|
|
employee: {
|
|
id: string;
|
|
employeeNo: string;
|
|
name: string;
|
|
title: string;
|
|
department: {
|
|
id: string;
|
|
name: string;
|
|
} | null;
|
|
} | null;
|
|
items: PayslipItem[];
|
|
};
|
|
|
|
export type PayrollMonthSummary = {
|
|
month: string;
|
|
totalNetAmount: number;
|
|
averageNetAmount: number;
|
|
issuedCount: number;
|
|
};
|
|
|
|
export async function fetchSalaryItems() {
|
|
return apiRequestData<{ items: SalaryItem[] }>("/api/payroll/items");
|
|
}
|
|
|
|
export async function createSalaryItem(payload: {
|
|
name: string;
|
|
itemType: SalaryItemType;
|
|
sortOrder: number;
|
|
enabled?: boolean;
|
|
}) {
|
|
return apiRequestData<SalaryItem>("/api/payroll/items", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function patchSalaryItem(
|
|
itemId: string,
|
|
payload: Partial<{
|
|
name: string;
|
|
itemType: SalaryItemType;
|
|
sortOrder: number;
|
|
enabled: boolean;
|
|
}>,
|
|
) {
|
|
return apiRequestData<SalaryItem>(`/api/payroll/items/${itemId}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function fetchEmployeeSalaryProfile(employeeId: string) {
|
|
return apiRequestData<{ employeeId: string; snapshots: EmployeeSalaryProfileSnapshot[] }>(
|
|
`/api/payroll/employees/${employeeId}/profile`,
|
|
);
|
|
}
|
|
|
|
export async function upsertEmployeeSalaryProfile(
|
|
employeeId: string,
|
|
payload: {
|
|
effectiveDate: string;
|
|
items: Array<{
|
|
salaryItemId: string;
|
|
monthlyAmount: number;
|
|
}>;
|
|
},
|
|
) {
|
|
return apiRequestData<{ employeeId: string; snapshots: EmployeeSalaryProfileSnapshot[] }>(
|
|
`/api/payroll/employees/${employeeId}/profile`,
|
|
{
|
|
method: "PUT",
|
|
body: JSON.stringify(payload),
|
|
},
|
|
);
|
|
}
|
|
|
|
export async function fetchEmployeePayslips(employeeId: string) {
|
|
return apiRequestData<{ employeeId: string; items: Payslip[] }>(`/api/payroll/employees/${employeeId}/payslips`);
|
|
}
|
|
|
|
export async function fetchPayslipsByMonth(month: string) {
|
|
return apiRequestData<{
|
|
month: string;
|
|
salaryItems: SalaryItem[];
|
|
items: Payslip[];
|
|
summary: {
|
|
total: number;
|
|
draft: number;
|
|
issued: number;
|
|
};
|
|
}>(`/api/payroll/payslips?month=${encodeURIComponent(month)}`);
|
|
}
|
|
|
|
export async function generatePayslips(month: string) {
|
|
return apiRequestData<{
|
|
month: string;
|
|
summary: {
|
|
total: number;
|
|
generated: number;
|
|
};
|
|
}>("/api/payroll/payslips/generate", {
|
|
method: "POST",
|
|
body: JSON.stringify({ month }),
|
|
});
|
|
}
|
|
|
|
export async function patchPayslip(
|
|
payslipId: string,
|
|
payload: {
|
|
items: Array<{
|
|
salaryItemId: string;
|
|
amount: number;
|
|
}>;
|
|
},
|
|
) {
|
|
return apiRequestData<Payslip>(`/api/payroll/payslips/${payslipId}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(payload),
|
|
});
|
|
}
|
|
|
|
export async function issuePayslips(month: string) {
|
|
return apiRequestData<{
|
|
month: string;
|
|
summary: {
|
|
total: number;
|
|
issued: number;
|
|
};
|
|
}>("/api/payroll/payslips/issue", {
|
|
method: "POST",
|
|
body: JSON.stringify({ month }),
|
|
});
|
|
}
|