@apptimate/core-lib 6.6.0 → 6.7.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
CHANGED
|
@@ -53,3 +53,8 @@ export async function getChartOfAccountsLookupShared(type?: string): Promise<IAp
|
|
|
53
53
|
const response = await sendRequest({ url: `${BASE}/chart-of-accounts/lookup`, method: "GET", params });
|
|
54
54
|
return response.responseData as IApiResponse;
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
export async function getDirectTransactionsShared(params?: any): Promise<IApiResponse> {
|
|
58
|
+
const response = await sendRequest({ url: `${BASE}/direct-transactions`, method: "GET", params });
|
|
59
|
+
return response.responseData as IApiResponse;
|
|
60
|
+
}
|
package/src/constants/menus.ts
CHANGED
|
@@ -253,6 +253,7 @@ export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
|
253
253
|
{ key: 'construction__hierarchy', label: 'Hierarchy', path: '/construction/hierarchy', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
254
254
|
{ key: 'construction__team', label: 'Team', path: '/construction/team', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
255
255
|
{ key: 'construction__budget', label: 'Budget', path: '/construction/budget', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
256
|
+
{ key: 'construction__expenses', label: 'Expenses', path: '/construction/expenses', module: 'Construction', defaultGroup: 'Project Planning', permission: null },
|
|
256
257
|
|
|
257
258
|
{ key: 'construction__main_contract', label: 'Client', path: '/construction/contracts/main-contract', module: 'Construction', defaultGroup: 'Contracts & Billing', permission: null },
|
|
258
259
|
{ key: 'construction__subcontractors', label: 'Subcontractors', path: '/construction/contracts/subcontractors', module: 'Construction', defaultGroup: 'Contracts & Billing', permission: null },
|
|
@@ -613,6 +614,7 @@ const PROJECT_KEY_MAPPING: Record<string, string> = {
|
|
|
613
614
|
'project_hierarchy': 'construction__hierarchy',
|
|
614
615
|
'project_team': 'construction__team',
|
|
615
616
|
'project_budget': 'construction__budget',
|
|
617
|
+
'project_expenses': 'construction__expenses',
|
|
616
618
|
'project_resource_calendar': 'construction__schedule_calendar',
|
|
617
619
|
'project_progress_billing': 'construction__ipcs',
|
|
618
620
|
'project_variations': 'construction__variations',
|
|
@@ -671,6 +673,7 @@ export const getProjectConstructionGroups = (projectId: string | number): MainMe
|
|
|
671
673
|
items: [
|
|
672
674
|
{ id: 'project_boq', label: 'Bill of Quantities (BOQ)', path: `/construction/projects/${projectId}/boq` },
|
|
673
675
|
{ id: 'project_boq_revisions', label: 'BOQ Revisions', path: `/construction/projects/${projectId}/boq/revisions` },
|
|
676
|
+
{ id: 'project_expenses', label: 'Direct Expenses', path: `/construction/projects/${projectId}/expenses` },
|
|
674
677
|
]
|
|
675
678
|
},
|
|
676
679
|
{
|
|
@@ -12,5 +12,6 @@ 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
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
|
+
active_project: { name: 'active_project', secretName: 'ACTIVE_PROJECT', encrypted: false } as IStorageOptions,
|
|
16
|
+
pos_fullscreen: { name: 'pos_fullscreen', secretName: 'POS_FULLSCREEN', encrypted: false } as IStorageOptions
|
|
16
17
|
};
|
package/src/utils/apiProxy.ts
CHANGED
|
@@ -117,6 +117,8 @@ export async function forwardApiProxyRequest(request: Request, pathSegments: str
|
|
|
117
117
|
const contentType = request.headers.get("content-type");
|
|
118
118
|
const organizationId = request.headers.get("x-organization-id") ?? selectedOrganizationId;
|
|
119
119
|
|
|
120
|
+
const tenantDomain = request.headers.get("x-tenant-domain");
|
|
121
|
+
|
|
120
122
|
if (accept) {
|
|
121
123
|
headers.set("accept", accept);
|
|
122
124
|
}
|
|
@@ -129,6 +131,10 @@ export async function forwardApiProxyRequest(request: Request, pathSegments: str
|
|
|
129
131
|
headers.set("x-organization-id", organizationId);
|
|
130
132
|
}
|
|
131
133
|
|
|
134
|
+
if (tenantDomain) {
|
|
135
|
+
headers.set("x-tenant-domain", tenantDomain);
|
|
136
|
+
}
|
|
137
|
+
|
|
132
138
|
if (token) {
|
|
133
139
|
headers.set("authorization", `Bearer ${token}`);
|
|
134
140
|
}
|
package/src/utils/httpClient.ts
CHANGED
|
@@ -113,6 +113,9 @@ export async function sendRequest<T = any>({ url, method, data, params, headers,
|
|
|
113
113
|
|
|
114
114
|
finalUrl = buildBrowserProxyUrl(finalUrl);
|
|
115
115
|
|
|
116
|
+
// Inject Tenant Domain dynamically for Database-per-Tenant isolation
|
|
117
|
+
defaultHeaders['X-Tenant-Domain'] = window.location.hostname;
|
|
118
|
+
|
|
116
119
|
// Automatically inject selected organization ID into every request
|
|
117
120
|
try {
|
|
118
121
|
const orgRaw = localStorage.getItem('selected_organization');
|
|
@@ -131,6 +134,22 @@ export async function sendRequest<T = any>({ url, method, data, params, headers,
|
|
|
131
134
|
defaultHeaders['Content-Type'] = 'application/json';
|
|
132
135
|
}
|
|
133
136
|
|
|
137
|
+
// Server-side Tenant Domain extraction
|
|
138
|
+
if (typeof window === 'undefined') {
|
|
139
|
+
try {
|
|
140
|
+
// Dynamically import next/headers to avoid client-side bundling issues
|
|
141
|
+
const nextHeaders = require('next/headers');
|
|
142
|
+
if (nextHeaders && typeof nextHeaders.headers === 'function') {
|
|
143
|
+
const host = nextHeaders.headers().get('host');
|
|
144
|
+
if (host) {
|
|
145
|
+
defaultHeaders['X-Tenant-Domain'] = host.split(':')[0];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
// Ignore if next/headers is unavailable
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
134
153
|
try {
|
|
135
154
|
const response = await fetch(finalUrl, {
|
|
136
155
|
method,
|