@apptimate/core-lib 5.3.0 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/api-services/email-services.client.ts +94 -0
- package/src/api-services/email-templates.client.ts +130 -0
- package/src/api-services/hr-attendance-shifts.client.ts +90 -0
- package/src/api-services/hr-attendance.client.ts +19 -0
- package/src/api-services/hr-employees.client.ts +8 -0
- package/src/api-services/hr-shift-templates.client.ts +68 -0
- package/src/api-services/inventory/brands.client.ts +2 -1
- package/src/api-services/inventory/categories.client.ts +2 -1
- package/src/api-services/inventory/inventory-settings.client.ts +2 -1
- package/src/api-services/inventory/items.client.ts +2 -1
- package/src/api-services/inventory/parties.client.ts +2 -1
- package/src/api-services/inventory/transaction.client.ts +2 -1
- package/src/api-services/inventory/uom-group.client.ts +2 -1
- package/src/api-services/inventory/uom.client.ts +2 -1
- package/src/client.ts +2 -0
- package/src/constants/menus.ts +61 -37
- package/src/constants/storageKeys.ts +2 -1
- package/src/index.ts +7 -1
- package/src/server.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { IApiResponse } from "../common/interfaces/ICommon";
|
|
2
|
+
import { sendRequest } from "../utils/httpClient";
|
|
3
|
+
|
|
4
|
+
const BASE = `${process.env.NEXT_PUBLIC_API_URL}/api`;
|
|
5
|
+
|
|
6
|
+
export type EmailProvider = "smtp";
|
|
7
|
+
export type EmailConnectionStatus = "draft" | "connected" | "verified" | "active" | "inactive" | "reauthorization_required" | "error" | "disconnected";
|
|
8
|
+
|
|
9
|
+
export interface EmailConnection {
|
|
10
|
+
id: number;
|
|
11
|
+
connection_name: string;
|
|
12
|
+
provider: EmailProvider;
|
|
13
|
+
display_name?: string | null;
|
|
14
|
+
from_name: string;
|
|
15
|
+
from_email: string;
|
|
16
|
+
reply_to_email?: string | null;
|
|
17
|
+
status: EmailConnectionStatus;
|
|
18
|
+
is_default: boolean;
|
|
19
|
+
verified_at?: string | null;
|
|
20
|
+
last_health_status?: "healthy" | "degraded" | "unhealthy" | "unknown" | null;
|
|
21
|
+
last_error_code?: string | null;
|
|
22
|
+
routes_count?: number;
|
|
23
|
+
has_password?: boolean;
|
|
24
|
+
smtp?: {
|
|
25
|
+
host: string;
|
|
26
|
+
port: number;
|
|
27
|
+
encryption: "tls" | "ssl" | "none";
|
|
28
|
+
username: string;
|
|
29
|
+
} | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface EmailConnectionRoute {
|
|
33
|
+
id: number;
|
|
34
|
+
email_connection_id: number;
|
|
35
|
+
module_code?: string | null;
|
|
36
|
+
message_type?: string | null;
|
|
37
|
+
document_type?: string | null;
|
|
38
|
+
is_active: boolean;
|
|
39
|
+
connection?: Pick<EmailConnection, "id" | "connection_name" | "provider">;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface EmailDelivery {
|
|
43
|
+
id: number;
|
|
44
|
+
uuid: string;
|
|
45
|
+
email_connection_id?: number | null;
|
|
46
|
+
provider: EmailProvider | "system";
|
|
47
|
+
message_type?: string | null;
|
|
48
|
+
recipient_summary: string[] | Record<string, unknown>;
|
|
49
|
+
subject: string;
|
|
50
|
+
status: "queued" | "processing" | "retrying" | "accepted" | "failed" | "cancelled";
|
|
51
|
+
attempt_count: number;
|
|
52
|
+
queued_at?: string | null;
|
|
53
|
+
accepted_at?: string | null;
|
|
54
|
+
failed_at?: string | null;
|
|
55
|
+
connection?: Pick<EmailConnection, "id" | "connection_name">;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface SmtpConnectionPayload {
|
|
59
|
+
id?: number;
|
|
60
|
+
connection_name: string;
|
|
61
|
+
from_name: string;
|
|
62
|
+
from_email: string;
|
|
63
|
+
reply_to_email?: string;
|
|
64
|
+
host: string;
|
|
65
|
+
port: number;
|
|
66
|
+
encryption: "tls" | "ssl" | "none";
|
|
67
|
+
username: string;
|
|
68
|
+
password?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function request<T>(url: string, method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", data?: unknown): Promise<IApiResponse<T>> {
|
|
72
|
+
const response = await sendRequest({ url, method, data });
|
|
73
|
+
return response.responseData as IApiResponse<T>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const listEmailConnections = () => request<EmailConnection[]>(`${BASE}/email-connections`, "GET");
|
|
77
|
+
export const revealSmtpConnectionPassword = (id: number) =>
|
|
78
|
+
request<{ password: string }>(`${BASE}/email-connections/${id}/smtp-secret`, "GET");
|
|
79
|
+
export const saveSmtpConnection = (data: SmtpConnectionPayload) => request<EmailConnection>(`${BASE}/email-connections/smtp`, "PUT", data);
|
|
80
|
+
export const verifyEmailConnection = (id: number) => request<EmailConnection>(`${BASE}/email-connections/${id}/verify`, "POST");
|
|
81
|
+
export const sendConnectionTest = (id: number, test_recipient: string) =>
|
|
82
|
+
request<null>(`${BASE}/email-connections/${id}/send-test`, "POST", { test_recipient });
|
|
83
|
+
export const activateEmailConnection = (id: number) => request<EmailConnection>(`${BASE}/email-connections/${id}/activate`, "POST");
|
|
84
|
+
export const deactivateEmailConnection = (id: number) => request<EmailConnection>(`${BASE}/email-connections/${id}/deactivate`, "POST");
|
|
85
|
+
export const deleteEmailConnection = (id: number) => request<null>(`${BASE}/email-connections/${id}`, "DELETE");
|
|
86
|
+
|
|
87
|
+
export const listEmailConnectionRoutes = () => request<EmailConnectionRoute[]>(`${BASE}/email-connection-routes`, "GET");
|
|
88
|
+
export const saveEmailConnectionRoute = (data: Omit<EmailConnectionRoute, "id" | "connection"> & { id?: number }) =>
|
|
89
|
+
request<EmailConnectionRoute>(`${BASE}/email-connection-routes${data.id ? `/${data.id}` : ""}`, data.id ? "PUT" : "POST", data);
|
|
90
|
+
export const deleteEmailConnectionRoute = (id: number) => request<null>(`${BASE}/email-connection-routes/${id}`, "DELETE");
|
|
91
|
+
|
|
92
|
+
export const listEmailDeliveries = () => request<{ data: EmailDelivery[] } | EmailDelivery[]>(`${BASE}/email-deliveries`, "GET");
|
|
93
|
+
export const retryEmailDelivery = (id: number, data?: { email_connection_id?: number; reason?: string }) =>
|
|
94
|
+
request<EmailDelivery>(`${BASE}/email-deliveries/${id}/retry`, "POST", data);
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { IApiResponse } from "../common/interfaces/ICommon";
|
|
2
|
+
import { sendRequest } from "../utils/httpClient";
|
|
3
|
+
|
|
4
|
+
const BASE = `${process.env.NEXT_PUBLIC_API_URL}/api/email-templates`;
|
|
5
|
+
|
|
6
|
+
export type EmailTemplateStatus = "active" | "inactive";
|
|
7
|
+
export type EmailTemplateFormat = "html" | "plain_text";
|
|
8
|
+
|
|
9
|
+
export interface EmailTemplate {
|
|
10
|
+
id: number;
|
|
11
|
+
organization_id: number;
|
|
12
|
+
name: string;
|
|
13
|
+
code: string;
|
|
14
|
+
description: string | null;
|
|
15
|
+
category: string;
|
|
16
|
+
subject: string;
|
|
17
|
+
html_body: string;
|
|
18
|
+
plain_text_body: string | null;
|
|
19
|
+
format: EmailTemplateFormat;
|
|
20
|
+
status: EmailTemplateStatus;
|
|
21
|
+
created_at: string;
|
|
22
|
+
updated_at: string;
|
|
23
|
+
creator?: { id: number; name: string } | null;
|
|
24
|
+
updater?: { id: number; name: string } | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface EmailTemplatePayload {
|
|
28
|
+
name: string;
|
|
29
|
+
code: string;
|
|
30
|
+
description?: string | null;
|
|
31
|
+
category: string;
|
|
32
|
+
subject: string;
|
|
33
|
+
html_body: string;
|
|
34
|
+
plain_text_body?: string | null;
|
|
35
|
+
format: EmailTemplateFormat;
|
|
36
|
+
status: EmailTemplateStatus;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface EmailTemplateListResult {
|
|
40
|
+
data: EmailTemplate[];
|
|
41
|
+
total: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface EmailTemplateToken {
|
|
45
|
+
key: string;
|
|
46
|
+
label: string;
|
|
47
|
+
data_type: string;
|
|
48
|
+
default_value: string | null;
|
|
49
|
+
sample_value: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface EmailTemplateTokenGroup {
|
|
53
|
+
key: string;
|
|
54
|
+
label: string;
|
|
55
|
+
tokens: EmailTemplateToken[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface EmailTemplateCategoryTokens {
|
|
59
|
+
category: string;
|
|
60
|
+
groups: EmailTemplateTokenGroup[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface RenderedEmailTemplate {
|
|
64
|
+
template_id: number;
|
|
65
|
+
subject: string;
|
|
66
|
+
html_body: string;
|
|
67
|
+
plain_text_body: string;
|
|
68
|
+
missing_tokens: string[];
|
|
69
|
+
unknown_tokens: string[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function getEmailTemplates(
|
|
73
|
+
params: Record<string, string | number> = {},
|
|
74
|
+
): Promise<IApiResponse<EmailTemplateListResult>> {
|
|
75
|
+
const query = new URLSearchParams(
|
|
76
|
+
Object.entries(params).reduce<Record<string, string>>((result, [key, value]) => {
|
|
77
|
+
result[key] = String(value);
|
|
78
|
+
return result;
|
|
79
|
+
}, {}),
|
|
80
|
+
).toString();
|
|
81
|
+
const response = await sendRequest({ url: `${BASE}${query ? `?${query}` : ""}`, method: "GET" });
|
|
82
|
+
return response.responseData as IApiResponse<EmailTemplateListResult>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function getEmailTemplate(id: number): Promise<IApiResponse<EmailTemplate>> {
|
|
86
|
+
const response = await sendRequest({ url: `${BASE}/${id}`, method: "GET" });
|
|
87
|
+
return response.responseData as IApiResponse<EmailTemplate>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function createEmailTemplate(
|
|
91
|
+
data: EmailTemplatePayload,
|
|
92
|
+
): Promise<IApiResponse<EmailTemplate>> {
|
|
93
|
+
const response = await sendRequest({ url: BASE, method: "POST", data });
|
|
94
|
+
return response.responseData as IApiResponse<EmailTemplate>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function updateEmailTemplate(
|
|
98
|
+
id: number,
|
|
99
|
+
data: EmailTemplatePayload,
|
|
100
|
+
): Promise<IApiResponse<EmailTemplate>> {
|
|
101
|
+
const response = await sendRequest({ url: `${BASE}/${id}`, method: "PUT", data });
|
|
102
|
+
return response.responseData as IApiResponse<EmailTemplate>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function deleteEmailTemplate(id: number): Promise<IApiResponse<null>> {
|
|
106
|
+
const response = await sendRequest({ url: `${BASE}/${id}`, method: "DELETE" });
|
|
107
|
+
return response.responseData as IApiResponse<null>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export async function getEmailTemplateCategoryTokens(
|
|
111
|
+
category: string,
|
|
112
|
+
): Promise<IApiResponse<EmailTemplateCategoryTokens>> {
|
|
113
|
+
const response = await sendRequest({
|
|
114
|
+
url: `${process.env.NEXT_PUBLIC_API_URL}/api/email-template-categories/${encodeURIComponent(category)}/tokens`,
|
|
115
|
+
method: "GET",
|
|
116
|
+
});
|
|
117
|
+
return response.responseData as IApiResponse<EmailTemplateCategoryTokens>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export async function previewEmailTemplate(
|
|
121
|
+
id: number,
|
|
122
|
+
tokenData: Record<string, string> = {},
|
|
123
|
+
): Promise<IApiResponse<RenderedEmailTemplate>> {
|
|
124
|
+
const response = await sendRequest({
|
|
125
|
+
url: `${BASE}/${id}/preview`,
|
|
126
|
+
method: "POST",
|
|
127
|
+
data: { token_data: tokenData },
|
|
128
|
+
});
|
|
129
|
+
return response.responseData as IApiResponse<RenderedEmailTemplate>;
|
|
130
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { sendRequest } from "../utils/httpClient";
|
|
2
|
+
import { IApiResponse } from "../common/interfaces/ICommon";
|
|
3
|
+
|
|
4
|
+
const callApi = async (url: string, method: "GET" | "POST", data?: any) => {
|
|
5
|
+
const response = await sendRequest({ url, method, data });
|
|
6
|
+
return response.responseData as IApiResponse;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const BASE_URL = `${process.env.NEXT_PUBLIC_API_URL}/api/hr`;
|
|
10
|
+
|
|
11
|
+
export const getEmployeeCalendar = async (employeeId: string | number, startDate: string, endDate: string, projectId?: string | number, workforceId?: string | number): Promise<IApiResponse> => {
|
|
12
|
+
const params: any = { start_date: startDate, end_date: endDate };
|
|
13
|
+
if (projectId) params.project_id = projectId;
|
|
14
|
+
if (workforceId) params.workforce_id = workforceId;
|
|
15
|
+
const queryParams = new URLSearchParams(params);
|
|
16
|
+
|
|
17
|
+
const url = employeeId === 'me'
|
|
18
|
+
? `${BASE_URL}/ess/me/calendar?${queryParams.toString()}`
|
|
19
|
+
: employeeId === 0
|
|
20
|
+
? `${BASE_URL}/calendar?${queryParams.toString()}` // For construction gangs
|
|
21
|
+
: `${BASE_URL}/employees/${employeeId}/calendar?${queryParams.toString()}`;
|
|
22
|
+
|
|
23
|
+
const response = await sendRequest({ url, method: "GET" });
|
|
24
|
+
return response.responseData as IApiResponse;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const toggleSegmentCancellation = async (employeeId: string | number, data: { roster_date: string, segment_no: number, reason?: string }): Promise<IApiResponse> => {
|
|
28
|
+
const url = employeeId === 'me'
|
|
29
|
+
? `${BASE_URL}/ess/me/calendar/cancel-segment`
|
|
30
|
+
: `${BASE_URL}/employees/${employeeId}/calendar/cancel-segment`;
|
|
31
|
+
|
|
32
|
+
return callApi(url, 'POST', { ...data, employee_id: employeeId === 'me' ? undefined : employeeId });
|
|
33
|
+
};
|
|
34
|
+
export const requestSegmentExchange = async (
|
|
35
|
+
employeeId: string | number,
|
|
36
|
+
data: { roster_date: string, segment_no: number, requester_id: number, responder_id: number, reason?: string }
|
|
37
|
+
): Promise<IApiResponse> => {
|
|
38
|
+
const url = employeeId === 'me'
|
|
39
|
+
? `${BASE_URL}/ess/me/calendar/exchange-segment`
|
|
40
|
+
: `${BASE_URL}/employees/${employeeId}/calendar/exchange-segment`;
|
|
41
|
+
|
|
42
|
+
return callApi(url, 'POST', { ...data, employee_id: employeeId === 'me' ? undefined : employeeId });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const cancelSegmentExchange = async (employeeId: string | number, exchangeId: number): Promise<IApiResponse> => {
|
|
46
|
+
const url = employeeId === 'me'
|
|
47
|
+
? `${BASE_URL}/ess/me/calendar/exchange-segment/${exchangeId}`
|
|
48
|
+
: `${BASE_URL}/employees/${employeeId}/calendar/exchange-segment/${exchangeId}`;
|
|
49
|
+
|
|
50
|
+
const response = await sendRequest({ url, method: "DELETE" });
|
|
51
|
+
return response.responseData as IApiResponse;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const getDailyOverview = async (date: string): Promise<IApiResponse> => {
|
|
55
|
+
const response = await sendRequest({ url: `${BASE_URL}/calendar/daily-overview?date=${date}`, method: "GET" });
|
|
56
|
+
return response.responseData as IApiResponse;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const getCalendarSummary = async (employeeId: string | number, month: string): Promise<IApiResponse> => {
|
|
60
|
+
const url = employeeId === 'me'
|
|
61
|
+
? `${BASE_URL}/ess/me/calendar/summary?month=${month}`
|
|
62
|
+
: `${BASE_URL}/employees/${employeeId}/calendar/summary?month=${month}`;
|
|
63
|
+
|
|
64
|
+
const response = await sendRequest({ url, method: "GET" });
|
|
65
|
+
return response.responseData as IApiResponse;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const getAttendanceDays = async (employeeId: string | number, startDate: string, endDate: string, projectId?: string | number, workforceId?: string | number): Promise<IApiResponse> => {
|
|
69
|
+
const params: any = { start_date: startDate, end_date: endDate };
|
|
70
|
+
if (employeeId !== 0 && employeeId !== 'me') params.employee_id = employeeId;
|
|
71
|
+
if (projectId) params.project_id = projectId;
|
|
72
|
+
if (workforceId) params.workforce_id = workforceId;
|
|
73
|
+
const queryParams = new URLSearchParams(params);
|
|
74
|
+
|
|
75
|
+
const url = employeeId === 'me'
|
|
76
|
+
? `${BASE_URL}/ess/me/attendance/days?${queryParams.toString()}`
|
|
77
|
+
: `${BASE_URL}/attendance/days?${queryParams.toString()}`;
|
|
78
|
+
|
|
79
|
+
const response = await sendRequest({ url, method: "GET" });
|
|
80
|
+
return response.responseData as IApiResponse;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const getPendingActions = async (employeeId: string | number): Promise<IApiResponse> => {
|
|
84
|
+
const url = employeeId === 'me'
|
|
85
|
+
? `${BASE_URL}/ess/me/calendar/pending-actions`
|
|
86
|
+
: `${BASE_URL}/employees/${employeeId}/calendar/pending-actions`;
|
|
87
|
+
|
|
88
|
+
const response = await sendRequest({ url, method: "GET" });
|
|
89
|
+
return response.responseData as IApiResponse;
|
|
90
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { sendRequest } from "../utils/httpClient";
|
|
2
|
+
import { IApiResponse } from "../common/interfaces/ICommon";
|
|
3
|
+
|
|
4
|
+
const BASE_URL = `${process.env.NEXT_PUBLIC_API_URL}/api/hr/attendance`;
|
|
5
|
+
|
|
6
|
+
export async function punchAttendance(data: any): Promise<IApiResponse> {
|
|
7
|
+
const response = await sendRequest({ url: `${BASE_URL}/punch`, method: "POST", data });
|
|
8
|
+
return response.responseData as IApiResponse;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function bulkPunchAttendance(data: { punches: any[] }): Promise<IApiResponse> {
|
|
12
|
+
const response = await sendRequest({ url: `${BASE_URL}/punches/bulk`, method: "POST", data });
|
|
13
|
+
return response.responseData as IApiResponse;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function getWorkforceAttendanceLookup(): Promise<IApiResponse> {
|
|
17
|
+
const response = await sendRequest({ url: `${process.env.NEXT_PUBLIC_API_URL}/api/construction/workforce/attendance-lookup`, method: "GET" });
|
|
18
|
+
return response.responseData as IApiResponse;
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { sendRequest, IApiResponse } from "../client";
|
|
2
|
+
|
|
3
|
+
const BASE = `${process.env.NEXT_PUBLIC_API_URL}/api/hr/employees`;
|
|
4
|
+
|
|
5
|
+
export async function getEmployeeLookup(): Promise<IApiResponse> {
|
|
6
|
+
const response = await sendRequest({ url: `${BASE}/lookup`, method: "GET" });
|
|
7
|
+
return response.responseData as IApiResponse;
|
|
8
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { sendRequest } from "../utils/httpClient";
|
|
2
|
+
import { IApiResponse } from "../common/interfaces/ICommon";
|
|
3
|
+
|
|
4
|
+
const BASE = `${process.env.NEXT_PUBLIC_API_URL}/api/hr/shift-templates`;
|
|
5
|
+
const ASSIGN_BASE = `${process.env.NEXT_PUBLIC_API_URL}/api/hr/employees`;
|
|
6
|
+
|
|
7
|
+
export const getShiftTemplates = async (page = 1, search = "", status = ""): Promise<IApiResponse> => {
|
|
8
|
+
const queryParams = new URLSearchParams({ page: page.toString() });
|
|
9
|
+
if (search) queryParams.append("search", search);
|
|
10
|
+
if (status) queryParams.append("status", status);
|
|
11
|
+
const response = await sendRequest({ url: `${BASE}?${queryParams.toString()}`, method: "GET" });
|
|
12
|
+
return response.responseData as IApiResponse;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const getShiftTemplate = async (id: string | number): Promise<IApiResponse> => {
|
|
16
|
+
const response = await sendRequest({ url: `${BASE}/${id}`, method: "GET" });
|
|
17
|
+
return response.responseData as IApiResponse;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const createShiftTemplate = async (data: any): Promise<IApiResponse> => {
|
|
21
|
+
const response = await sendRequest({ url: BASE, method: "POST", data });
|
|
22
|
+
return response.responseData as IApiResponse;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const updateShiftTemplate = async (id: string | number, data: any): Promise<IApiResponse> => {
|
|
26
|
+
const response = await sendRequest({ url: `${BASE}/${id}`, method: "PUT", data });
|
|
27
|
+
return response.responseData as IApiResponse;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const deleteShiftTemplate = async (id: string | number): Promise<IApiResponse> => {
|
|
31
|
+
const response = await sendRequest({ url: `${BASE}/${id}`, method: "DELETE" });
|
|
32
|
+
return response.responseData as IApiResponse;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const getShiftTemplateLookup = async (): Promise<IApiResponse> => {
|
|
36
|
+
const response = await sendRequest({ url: `${BASE}/lookup`, method: "GET" });
|
|
37
|
+
return response.responseData as IApiResponse;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const getEmployeeShiftAssignment = async (employeeId: string | number): Promise<IApiResponse> => {
|
|
41
|
+
const response = await sendRequest({ url: `${ASSIGN_BASE}/${employeeId}/shift-assignment`, method: "GET" });
|
|
42
|
+
return response.responseData as IApiResponse;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const assignShiftToEmployee = async (employeeId: string | number, data: any): Promise<IApiResponse> => {
|
|
46
|
+
const response = await sendRequest({ url: `${ASSIGN_BASE}/${employeeId}/shift-assignment`, method: "POST", data });
|
|
47
|
+
return response.responseData as IApiResponse;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const getTemplateAssignments = async (templateId: string | number): Promise<IApiResponse> => {
|
|
51
|
+
const response = await sendRequest({ url: `${BASE}/${templateId}/assignments`, method: "GET" });
|
|
52
|
+
return response.responseData as IApiResponse;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export async function assignEmployeesToTemplate(templateId: number, data: any): Promise<IApiResponse> {
|
|
56
|
+
const response = await sendRequest({ url: `${BASE}/${templateId}/assignments`, method: "POST", data });
|
|
57
|
+
return response.responseData as IApiResponse;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function updateTemplateAssignment(templateId: number, assignmentId: number, data: any): Promise<IApiResponse> {
|
|
61
|
+
const response = await sendRequest({ url: `${BASE}/${templateId}/assignments/${assignmentId}`, method: "PUT", data });
|
|
62
|
+
return response.responseData as IApiResponse;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const unassignEmployee = async (templateId: string | number, assignmentId: string | number): Promise<IApiResponse> => {
|
|
66
|
+
const response = await sendRequest({ url: `${BASE}/${templateId}/assignments/${assignmentId}`, method: "DELETE" });
|
|
67
|
+
return response.responseData as IApiResponse;
|
|
68
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { sendRequest
|
|
3
|
+
import { sendRequest } from "../../utils/httpClient";
|
|
4
|
+
import { IApiResponse } from "../../common/interfaces/ICommon";
|
|
4
5
|
|
|
5
6
|
const BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";
|
|
6
7
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { sendRequest
|
|
1
|
+
import { sendRequest } from "../../utils/httpClient";
|
|
2
|
+
import { IApiResponse } from "../../common/interfaces/ICommon";
|
|
2
3
|
|
|
3
4
|
const INV_BASE = `${process.env.NEXT_PUBLIC_API_URL}/api/inventory`;
|
|
4
5
|
const FIN_BASE = `${process.env.NEXT_PUBLIC_API_URL}/api/finance`;
|
package/src/client.ts
CHANGED
|
@@ -13,4 +13,6 @@ export * from './utils/currencyService';
|
|
|
13
13
|
|
|
14
14
|
export * from './api-services/procurement.client';
|
|
15
15
|
export * from './api-services/printable-templates.client';
|
|
16
|
+
export * from './api-services/email-templates.client';
|
|
17
|
+
export * from './api-services/email-services.client';
|
|
16
18
|
export * from './schemas/approvalWorkflowSchema';
|
package/src/constants/menus.ts
CHANGED
|
@@ -85,11 +85,13 @@ export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
|
85
85
|
{ key: 'core__feature_registry', label: 'Feature Registry', path: '/system/features', module: 'Core', defaultGroup: 'System Auditing', permission: 'feature.view' },
|
|
86
86
|
{ key: 'core__menu_config', label: 'Menu Configuration', path: '/menu-config', module: 'Core', defaultGroup: 'System', permission: 'menu_config.view' },
|
|
87
87
|
{ key: 'core__printables', label: 'Printable Templates', path: '/system/printables', module: 'Core', defaultGroup: 'System', permission: 'printable_template.view' },
|
|
88
|
+
{ key: 'core__email_templates', label: 'Email Templates', path: '/system/email-templates', module: 'Core', defaultGroup: 'System', permission: 'email_template.view' },
|
|
88
89
|
{ key: 'core__template_groups', label: 'Template Groups', path: '/system/template-groups', module: 'Core', defaultGroup: 'System', permission: 'template_group.view' },
|
|
89
90
|
{ key: 'core__warehouses', label: 'Warehouses', path: '/warehouses', module: 'Core', defaultGroup: 'Resources', permission: 'warehouse.view' },
|
|
90
91
|
{ key: 'core__terminals', label: 'Terminals', path: '/terminals', module: 'Core', defaultGroup: 'Resources', permission: 'terminal.view' },
|
|
91
92
|
{ key: 'core__currencies', label: 'Currencies', path: '/currencies', module: 'Core', defaultGroup: 'Resources', permission: 'currency.view' },
|
|
92
93
|
{ key: 'core__settings', label: 'Settings', path: '/settings', module: 'Core', defaultGroup: 'Configuration', permission: 'core_setting.view' },
|
|
94
|
+
{ key: 'core__email_services', label: 'Integrations', path: '/settings/integrations', module: 'Core', defaultGroup: 'Configuration', permission: 'email_connection.view' },
|
|
93
95
|
{ key: 'core__approval_workflows', label: 'Approval Workflows', path: '/settings/approvals', module: 'Core', defaultGroup: 'Configuration', permission: null },
|
|
94
96
|
|
|
95
97
|
// ── Inventory Module ──
|
|
@@ -240,35 +242,38 @@ export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
|
240
242
|
// ── Construction Module ──
|
|
241
243
|
{ key: 'construction__dashboard', label: 'Overview', path: '/construction', module: 'Construction', defaultGroup: 'Overview', permission: null },
|
|
242
244
|
|
|
243
|
-
|
|
244
|
-
{ key: '
|
|
245
|
-
{ key: '
|
|
246
|
-
{ key: '
|
|
247
|
-
{ key: '
|
|
248
|
-
{ key: '
|
|
245
|
+
// ── Client Portal Module ──
|
|
246
|
+
{ key: 'client_portal__dashboard', label: 'Overview', path: '/construction-customers', module: 'Client Portal', defaultGroup: 'Overview', permission: null },
|
|
247
|
+
{ key: 'construction__projects', label: 'Projects', path: '/construction/projects', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
248
|
+
{ key: 'construction__rate_cards', label: 'Rate Cards', path: '/construction/rate-cards', module: 'Construction', defaultGroup: 'Estimation & BOQ', permission: null },
|
|
249
|
+
{ key: 'construction__schedule_calendar', label: 'Resource Calendar', path: '/construction/scheduling/calendar', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
250
|
+
{ key: 'construction__hierarchy', label: 'Hierarchy', path: '/construction/hierarchy', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
251
|
+
{ key: 'construction__team', label: 'Team', path: '/construction/team', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
252
|
+
{ key: 'construction__budget', label: 'Budget', path: '/construction/budget', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
249
253
|
|
|
250
254
|
{ key: 'construction__main_contract', label: 'Main Contract', path: '/construction/contracts/main-contract', module: 'Construction', defaultGroup: 'Contracts & Billing', permission: null },
|
|
251
255
|
{ key: 'construction__subcontractors', label: 'Subcontractors', path: '/construction/contracts/subcontractors', module: 'Construction', defaultGroup: 'Contracts & Billing', permission: null },
|
|
252
256
|
{ key: 'construction__ipcs', label: 'Progress Billing', path: '/construction/contracts/progress-billing', module: 'Construction', defaultGroup: 'Contracts & Billing', permission: null },
|
|
253
257
|
{ key: 'construction__variations', label: 'Subcontractor Variations', path: '/construction/variations', module: 'Construction', defaultGroup: 'Contracts & Billing', permission: null },
|
|
254
|
-
{ key: 'construction__boq', label: 'Bill of Quantities (BOQ)', path: '/construction/boq', module: 'Construction', defaultGroup: '
|
|
255
|
-
{ key: 'construction__boq_revisions', label: 'BOQ Revisions', path: '/construction/boq/revisions', module: 'Construction', defaultGroup: '
|
|
256
|
-
{ key: 'construction__assemblies', label: 'Assemblies', path: '/construction/assemblies', module: 'Construction', defaultGroup: '
|
|
257
|
-
{ key: 'construction__assembly_groups', label: 'Assembly Groups', path: '/construction/assembly-groups', module: 'Construction', defaultGroup: '
|
|
258
|
+
{ key: 'construction__boq', label: 'Bill of Quantities (BOQ)', path: '/construction/boq', module: 'Construction', defaultGroup: 'Estimation & BOQ', permission: null },
|
|
259
|
+
{ key: 'construction__boq_revisions', label: 'BOQ Revisions', path: '/construction/boq/revisions', module: 'Construction', defaultGroup: 'Estimation & BOQ', permission: null },
|
|
260
|
+
{ key: 'construction__assemblies', label: 'Assemblies', path: '/construction/assemblies', module: 'Construction', defaultGroup: 'Estimation & BOQ', permission: null },
|
|
261
|
+
{ key: 'construction__assembly_groups', label: 'Assembly Groups', path: '/construction/assembly-groups', module: 'Construction', defaultGroup: 'Estimation & BOQ', permission: null },
|
|
258
262
|
|
|
259
263
|
|
|
260
264
|
|
|
261
|
-
{ key: 'construction__workforce', label: 'Workforce Master', path: '/construction/workforce', module: 'Construction', defaultGroup: 'Workforce', permission: null },
|
|
262
|
-
{ key: 'construction__workforce_allocation', label: 'Workforce Allocation', path: '/construction/workforce/allocation', module: 'Construction', defaultGroup: 'Workforce', permission: null },
|
|
263
|
-
{ key: 'construction__shifts', label: 'Shift Master', path: '/construction/shifts', module: 'Construction', defaultGroup: 'Workforce', permission: null },
|
|
264
|
-
{ key: 'construction__attendance', label: 'Attendance & Timesheets', path: '/construction/attendance', module: 'Construction', defaultGroup: 'Workforce', permission: null },
|
|
265
|
+
{ key: 'construction__workforce', label: 'Workforce Master', path: '/construction/workforce', module: 'Construction', defaultGroup: 'Workforce Management', permission: null },
|
|
266
|
+
{ key: 'construction__workforce_allocation', label: 'Workforce Allocation', path: '/construction/workforce/allocation', module: 'Construction', defaultGroup: 'Workforce Management', permission: null },
|
|
267
|
+
{ key: 'construction__shifts', label: 'Shift Master', path: '/construction/shifts', module: 'Construction', defaultGroup: 'Workforce Management', permission: null },
|
|
268
|
+
{ key: 'construction__attendance', label: 'Attendance & Timesheets', path: '/construction/attendance', module: 'Construction', defaultGroup: 'Workforce Management', permission: null },
|
|
265
269
|
|
|
266
|
-
{ key: 'construction__equipment_types', label: 'Equipment Types', path: '/construction/equipment/types', module: 'Construction', defaultGroup: '
|
|
267
|
-
{ key: 'construction__equipment', label: 'Equipments', path: '/construction/equipment', module: 'Construction', defaultGroup: '
|
|
268
|
-
{ key: 'construction__equipment_allocation', label: 'Equipment Allocation', path: '/construction/equipment/allocation', module: 'Construction', defaultGroup: '
|
|
269
|
-
{ key: 'construction__fuel_logs', label: 'Fuel Logs', path: '/construction/equipment/fuel-logs', module: 'Construction', defaultGroup: '
|
|
270
|
-
{ key: 'construction__maintenance', label: 'Maintenance', path: '/construction/equipment/maintenance', module: 'Construction', defaultGroup: '
|
|
270
|
+
{ key: 'construction__equipment_types', label: 'Equipment Types', path: '/construction/equipment/types', module: 'Construction', defaultGroup: 'Plant & Equipment', permission: null },
|
|
271
|
+
{ key: 'construction__equipment', label: 'Equipments', path: '/construction/equipment', module: 'Construction', defaultGroup: 'Plant & Equipment', permission: null },
|
|
272
|
+
{ key: 'construction__equipment_allocation', label: 'Equipment Allocation', path: '/construction/equipment/allocation', module: 'Construction', defaultGroup: 'Plant & Equipment', permission: null },
|
|
273
|
+
{ key: 'construction__fuel_logs', label: 'Fuel Logs', path: '/construction/equipment/fuel-logs', module: 'Construction', defaultGroup: 'Plant & Equipment', permission: null },
|
|
274
|
+
{ key: 'construction__maintenance', label: 'Maintenance', path: '/construction/equipment/maintenance', module: 'Construction', defaultGroup: 'Plant & Equipment', permission: null },
|
|
271
275
|
|
|
276
|
+
{ key: 'construction__site_engineer', label: 'Site Engineer', path: '/construction/dashboard/site-engineer', module: 'Construction', defaultGroup: 'Site Execution', permission: null },
|
|
272
277
|
{ key: 'construction__dsr', label: 'Daily Site Reports', path: '/construction/site-execution/dsr', module: 'Construction', defaultGroup: 'Site Execution', permission: null },
|
|
273
278
|
{ key: 'construction__progress', label: 'Progress Measurement', path: '/construction/site-execution/progress', module: 'Construction', defaultGroup: 'Site Execution', permission: null },
|
|
274
279
|
{ key: 'construction__subcontractor_progress', label: 'Subcontractor Progress', path: '/construction/site-execution/subcontractor-progress', module: 'Construction', defaultGroup: 'Site Execution', permission: null },
|
|
@@ -380,7 +385,7 @@ export const MENU_PRESETS: MenuPreset[] = [
|
|
|
380
385
|
'core__warehouses', 'core__terminals',
|
|
381
386
|
'core__activity_logs', 'core__api_requests', 'core__feature_access_logs',
|
|
382
387
|
'core__issue_logs', 'core__feature_registry', 'core__menu_config',
|
|
383
|
-
'core__printables', 'core__template_groups', 'core__currencies', 'core__settings', 'core__approval_workflows',
|
|
388
|
+
'core__printables', 'core__email_templates', 'core__template_groups', 'core__currencies', 'core__settings', 'core__email_services', 'core__approval_workflows',
|
|
384
389
|
],
|
|
385
390
|
},
|
|
386
391
|
{
|
|
@@ -506,54 +511,65 @@ export const MENU_PRESETS: MenuPreset[] = [
|
|
|
506
511
|
{
|
|
507
512
|
id: 'construction',
|
|
508
513
|
label: 'Construction',
|
|
509
|
-
iconName: '
|
|
514
|
+
iconName: 'Hammer',
|
|
510
515
|
secondaryItems: [
|
|
516
|
+
// 1. Overview
|
|
511
517
|
'construction__dashboard',
|
|
518
|
+
// 2. Project Planning
|
|
512
519
|
'construction__projects',
|
|
513
|
-
'
|
|
520
|
+
'construction__schedule_calendar',
|
|
514
521
|
'construction__hierarchy',
|
|
515
|
-
'construction__team',
|
|
516
522
|
'construction__budget',
|
|
517
|
-
'
|
|
518
|
-
|
|
519
|
-
'construction__pos',
|
|
520
|
-
'construction__grns',
|
|
521
|
-
'construction__site_ledger',
|
|
522
|
-
'construction__site_issues',
|
|
523
|
-
'construction__wastage_returns',
|
|
524
|
-
'construction__variations',
|
|
523
|
+
'construction__team',
|
|
524
|
+
// 3. Estimation & BOQ
|
|
525
525
|
'construction__boq',
|
|
526
526
|
'construction__boq_revisions',
|
|
527
|
+
'construction__rate_cards',
|
|
527
528
|
'construction__assemblies',
|
|
528
529
|
'construction__assembly_groups',
|
|
530
|
+
// 4. Contracts & Billing
|
|
531
|
+
'construction__main_contract',
|
|
532
|
+
'construction__subcontractors',
|
|
533
|
+
'construction__ipcs',
|
|
534
|
+
'construction__variations',
|
|
535
|
+
// 5. Workforce Management
|
|
529
536
|
'construction__workforce',
|
|
530
537
|
'construction__workforce_allocation',
|
|
531
538
|
'construction__shifts',
|
|
532
539
|
'construction__attendance',
|
|
540
|
+
// 6. Plant & Equipment
|
|
533
541
|
'construction__equipment_types',
|
|
534
542
|
'construction__equipment',
|
|
535
543
|
'construction__equipment_allocation',
|
|
536
544
|
'construction__fuel_logs',
|
|
537
545
|
'construction__maintenance',
|
|
538
|
-
|
|
539
|
-
'
|
|
540
|
-
'construction__subcontractors',
|
|
541
|
-
'construction__ipcs',
|
|
546
|
+
// 7. Site Execution
|
|
547
|
+
'construction__site_engineer',
|
|
542
548
|
'construction__dsr',
|
|
543
549
|
'construction__progress',
|
|
544
550
|
'construction__subcontractor_progress',
|
|
545
551
|
'construction__change_orders',
|
|
552
|
+
'construction__mtrs',
|
|
553
|
+
'construction__prs',
|
|
554
|
+
'construction__pos',
|
|
555
|
+
'construction__grns',
|
|
556
|
+
'construction__site_ledger',
|
|
557
|
+
'construction__site_issues',
|
|
558
|
+
'construction__wastage_returns',
|
|
559
|
+
// 8. Document Control
|
|
546
560
|
'construction__drawings',
|
|
547
|
-
'construction__transmittals',
|
|
548
561
|
'construction__rfis',
|
|
562
|
+
'construction__transmittals',
|
|
563
|
+
// 9. Quality & Safety
|
|
549
564
|
'construction__quality_ir',
|
|
550
565
|
'construction__quality_ncr',
|
|
551
566
|
'construction__punch_list',
|
|
552
567
|
'construction__material_testing',
|
|
553
568
|
'construction__safety_incidents',
|
|
554
569
|
'construction__ptw',
|
|
555
|
-
|
|
570
|
+
// 10. Configuration
|
|
556
571
|
'construction__project_categories',
|
|
572
|
+
'construction__test_types',
|
|
557
573
|
'construction__settings',
|
|
558
574
|
],
|
|
559
575
|
},
|
|
@@ -564,6 +580,14 @@ export const MENU_PRESETS: MenuPreset[] = [
|
|
|
564
580
|
secondaryItems: [
|
|
565
581
|
...CRM_SECONDARY_ITEM_KEYS,
|
|
566
582
|
],
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
id: 'site_engineer',
|
|
586
|
+
label: 'Site Engineer',
|
|
587
|
+
iconName: 'Wrench',
|
|
588
|
+
secondaryItems: [
|
|
589
|
+
'construction__site_engineer',
|
|
590
|
+
],
|
|
567
591
|
}
|
|
568
592
|
],
|
|
569
593
|
},
|
|
@@ -11,5 +11,6 @@ export const cookie = {
|
|
|
11
11
|
export const local_storage = {
|
|
12
12
|
user_info: { name: 'user_info', secretName: 'USER_INFO_SECRET', encrypted: false } as IStorageOptions,
|
|
13
13
|
selected_organization: { name: 'selected_organization', secretName: 'SELECTED_ORG', encrypted: false } as IStorageOptions,
|
|
14
|
-
sales_terminal: { name: 'sales_terminal', secretName: 'SALES_TERMINAL', encrypted: false } as IStorageOptions
|
|
14
|
+
sales_terminal: { name: 'sales_terminal', secretName: 'SALES_TERMINAL', encrypted: false } as IStorageOptions,
|
|
15
|
+
active_project: { name: 'active_project', secretName: 'ACTIVE_PROJECT', encrypted: false } as IStorageOptions
|
|
15
16
|
};
|
package/src/index.ts
CHANGED
|
@@ -10,4 +10,10 @@ export * from './api-services/inventory/uom.client';
|
|
|
10
10
|
export * from './api-services/inventory/uom-group.client';
|
|
11
11
|
export * from './api-services/inventory/parties.client';
|
|
12
12
|
export * from './api-services/inventory/transaction.client';
|
|
13
|
-
export * from './utils/PriceCalculationService';
|
|
13
|
+
export * from './utils/PriceCalculationService';
|
|
14
|
+
export * from './api-services/hr-attendance.client';
|
|
15
|
+
export * from './api-services/hr-attendance-shifts.client';
|
|
16
|
+
export * from './api-services/hr-shift-templates.client';
|
|
17
|
+
export * from './api-services/hr-employees.client';
|
|
18
|
+
export * from './api-services/email-services.client';
|
|
19
|
+
export * from './api-services/email-templates.client';
|
package/src/server.ts
CHANGED