Files
zerp/frontend/src/lib/api/hrAdmin.ts
Talal Sharabi 72ed9a2ff5 feat(hr): Complete HR module with Employee Portal, Loans, Leave, Purchase Requests, Contracts
- Database: Add Loan, LoanInstallment, PurchaseRequest, LeaveEntitlement, EmployeeContract models
- Database: Extend Attendance with ZK Tico fields (sourceDeviceId, externalId, rawData)
- Database: Add Employee.attendancePin for device mapping
- Backend: HR admin - Loans, Purchase Requests, Leave entitlements, Employee contracts CRUD
- Backend: Leave reject, bulk attendance sync (ZK Tico ready)
- Backend: Employee Portal API - scoped by employeeId (loans, leaves, purchase-requests, attendance, salaries)
- Frontend: Employee Portal - dashboard, loans, leave, purchase-requests, attendance, salaries
- Frontend: HR Admin - new tabs for Leaves, Loans, Purchase Requests, Contracts (approve/reject)
- Dashboard: Add My Portal link
- No destructive schema changes; additive migrations only

Made-with: Cursor
2026-03-04 19:44:09 +04:00

77 lines
4.4 KiB
TypeScript

import { api } from '../api'
export const hrAdminAPI = {
// Leaves
getLeaves: async (params?: { employeeId?: string; status?: string; page?: number; pageSize?: number }) => {
const q = new URLSearchParams()
if (params?.employeeId) q.append('employeeId', params.employeeId)
if (params?.status) q.append('status', params.status)
if (params?.page) q.append('page', String(params.page))
if (params?.pageSize) q.append('pageSize', String(params.pageSize))
const res = await api.get(`/hr/leaves?${q}`)
return { leaves: res.data.data || [], pagination: res.data.pagination }
},
approveLeave: (id: string) => api.post(`/hr/leaves/${id}/approve`),
rejectLeave: (id: string, rejectedReason: string) => api.post(`/hr/leaves/${id}/reject`, { rejectedReason }),
// Loans
getLoans: async (params?: { employeeId?: string; status?: string; page?: number; pageSize?: number }) => {
const q = new URLSearchParams()
if (params?.employeeId) q.append('employeeId', params.employeeId)
if (params?.status) q.append('status', params.status)
if (params?.page) q.append('page', String(params.page))
if (params?.pageSize) q.append('pageSize', String(params.pageSize))
const res = await api.get(`/hr/loans?${q}`)
return { loans: res.data.data || [], pagination: res.data.pagination }
},
getLoanById: (id: string) => api.get(`/hr/loans/${id}`),
createLoan: (data: { employeeId: string; type: string; amount: number; installments?: number; reason?: string }) =>
api.post('/hr/loans', data),
approveLoan: (id: string, startDate?: string) => api.post(`/hr/loans/${id}/approve`, { startDate: startDate || new Date().toISOString().split('T')[0] }),
rejectLoan: (id: string, rejectedReason: string) => api.post(`/hr/loans/${id}/reject`, { rejectedReason }),
payInstallment: (loanId: string, installmentId: string, paidDate?: string) =>
api.post(`/hr/loans/${loanId}/pay-installment`, { installmentId, paidDate: paidDate || new Date().toISOString().split('T')[0] }),
// Purchase Requests
getPurchaseRequests: async (params?: { employeeId?: string; status?: string; page?: number; pageSize?: number }) => {
const q = new URLSearchParams()
if (params?.employeeId) q.append('employeeId', params.employeeId)
if (params?.status) q.append('status', params.status)
if (params?.page) q.append('page', String(params.page))
if (params?.pageSize) q.append('pageSize', String(params.pageSize))
const res = await api.get(`/hr/purchase-requests?${q}`)
return { purchaseRequests: res.data.data || [], pagination: res.data.pagination }
},
approvePurchaseRequest: (id: string) => api.post(`/hr/purchase-requests/${id}/approve`),
rejectPurchaseRequest: (id: string, rejectedReason: string) => api.post(`/hr/purchase-requests/${id}/reject`, { rejectedReason }),
// Leave Entitlements
getLeaveBalance: (employeeId: string, year?: number) => {
const q = year ? `?year=${year}` : ''
return api.get(`/hr/leave-balance/${employeeId}${q}`).then((r) => r.data.data)
},
getLeaveEntitlements: (params?: { employeeId?: string; year?: number }) => {
const q = new URLSearchParams()
if (params?.employeeId) q.append('employeeId', params.employeeId)
if (params?.year) q.append('year', String(params.year))
return api.get(`/hr/leave-entitlements?${q}`).then((r) => r.data.data)
},
upsertLeaveEntitlement: (data: { employeeId: string; year: number; leaveType: string; totalDays: number; carriedOver?: number; notes?: string }) =>
api.post('/hr/leave-entitlements', data),
// Employee Contracts
getContracts: async (params?: { employeeId?: string; status?: string; page?: number; pageSize?: number }) => {
const q = new URLSearchParams()
if (params?.employeeId) q.append('employeeId', params.employeeId)
if (params?.status) q.append('status', params.status)
if (params?.page) q.append('page', String(params.page))
if (params?.pageSize) q.append('pageSize', String(params.pageSize))
const res = await api.get(`/hr/contracts?${q}`)
return { contracts: res.data.data || [], pagination: res.data.pagination }
},
createContract: (data: { employeeId: string; type: string; startDate: string; endDate?: string; salary: number; documentUrl?: string; notes?: string }) =>
api.post('/hr/contracts', data),
updateContract: (id: string, data: Partial<{ type: string; endDate: string; salary: number; status: string; notes: string }>) =>
api.put(`/hr/contracts/${id}`, data),
}