@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apptimate/core-lib",
3
- "version": "6.6.0",
3
+ "version": "6.7.0",
4
4
  "main": "src/index.ts",
5
5
  "types": "src/index.ts",
6
6
  "publishConfig": {
@@ -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
+ }
@@ -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
  };
@@ -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
  }
@@ -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,