RBAC: Phase 1-3, Total Salary fix, employee creation fix, permission groups, backup script

Made-with: Cursor
This commit is contained in:
Talal Sharabi
2026-03-04 19:31:08 +04:00
parent 6034f774ed
commit 8edeaf10f5
46 changed files with 2751 additions and 598 deletions

View File

@@ -132,12 +132,34 @@ export interface PositionRole {
_count?: { employees: number };
}
export interface CreatePositionData {
title: string;
titleAr?: string;
code: string;
departmentId: string;
level?: number;
description?: string;
}
export const positionsAPI = {
getAll: async (): Promise<PositionRole[]> => {
const response = await api.get('/admin/positions');
return response.data.data || [];
},
create: async (data: CreatePositionData): Promise<PositionRole> => {
const response = await api.post('/admin/positions', data);
return response.data.data;
},
update: async (
id: string,
data: Partial<CreatePositionData & { isActive?: boolean }>
): Promise<PositionRole> => {
const response = await api.put(`/admin/positions/${id}`, data);
return response.data.data;
},
updatePermissions: async (
positionId: string,
permissions: Array<{ module: string; resource: string; actions: string[] }>
@@ -189,6 +211,53 @@ export const rolesAPI = {
},
};
// Permission Groups API (Phase 3 - multi-group)
export interface PermissionGroup {
id: string;
name: string;
nameAr?: string | null;
description?: string | null;
isActive: boolean;
permissions: { id: string; module: string; resource: string; actions: string[] }[];
_count?: { userRoles: number };
}
export const permissionGroupsAPI = {
getAll: async (): Promise<PermissionGroup[]> => {
const response = await api.get('/admin/permission-groups');
return response.data.data || [];
},
create: async (data: { name: string; nameAr?: string; description?: string }) => {
const response = await api.post('/admin/permission-groups', data);
return response.data.data;
},
update: async (id: string, data: Partial<{ name: string; nameAr: string; description: string; isActive: boolean }>) => {
const response = await api.put(`/admin/permission-groups/${id}`, data);
return response.data.data;
},
updatePermissions: async (
id: string,
permissions: Array<{ module: string; resource: string; actions: string[] }>
) => {
const response = await api.put(`/admin/permission-groups/${id}/permissions`, { permissions });
return response.data.data;
},
};
export const userRolesAPI = {
getAll: async (userId: string) => {
const response = await api.get(`/admin/users/${userId}/roles`);
return response.data.data || [];
},
assign: async (userId: string, roleId: string) => {
const response = await api.post(`/admin/users/${userId}/roles`, { roleId });
return response.data.data;
},
remove: async (userId: string, roleId: string) => {
await api.delete(`/admin/users/${userId}/roles/${roleId}`);
},
};
// Audit Logs API
export interface AuditLog {
id: string;

View File

@@ -84,8 +84,12 @@ export const employeesAPI = {
const response = await api.get(`/hr/employees?${params.toString()}`)
const { data, pagination } = response.data
const employees = (data || []).map((e: any) => ({
...e,
baseSalary: e.baseSalary ?? e.basicSalary ?? 0,
}))
return {
employees: data || [],
employees,
total: pagination?.total || 0,
page: pagination?.page || 1,
pageSize: pagination?.pageSize || 20,
@@ -96,7 +100,8 @@ export const employeesAPI = {
// Get single employee by ID
getById: async (id: string): Promise<Employee> => {
const response = await api.get(`/hr/employees/${id}`)
return response.data.data
const e = response.data.data
return e ? { ...e, baseSalary: e.baseSalary ?? e.basicSalary ?? 0 } : e
},
// Create new employee
@@ -118,10 +123,40 @@ export const employeesAPI = {
}
// Departments API
export interface Department {
id: string
name: string
nameAr?: string | null
code: string
parentId?: string | null
parent?: { id: string; name: string; nameAr?: string | null }
description?: string | null
isActive?: boolean
children?: Department[]
employees?: any[]
positions?: any[]
_count?: { children: number; employees: number }
}
export const departmentsAPI = {
getAll: async (): Promise<any[]> => {
const response = await api.get('/hr/departments')
return response.data.data
},
getHierarchy: async (): Promise<Department[]> => {
const response = await api.get('/hr/departments/hierarchy')
return response.data.data
},
create: async (data: { name: string; nameAr?: string; code: string; parentId?: string; description?: string }) => {
const response = await api.post('/hr/departments', data)
return response.data.data
},
update: async (id: string, data: Partial<{ name: string; nameAr: string; code: string; parentId: string | null; description: string; isActive: boolean }>) => {
const response = await api.put(`/hr/departments/${id}`, data)
return response.data.data
},
delete: async (id: string) => {
await api.delete(`/hr/departments/${id}`)
}
}