@apptimate/core-lib 4.8.0 → 4.9.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
|
@@ -15,6 +15,23 @@ export async function getItemBatches(itemId: number, params: Record<string, stri
|
|
|
15
15
|
return response.responseData as IApiResponse;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
export async function evaluatePriceLists(data: {
|
|
19
|
+
party_id?: number | null;
|
|
20
|
+
transaction_type: string;
|
|
21
|
+
items: Array<{ variant_id: number }>;
|
|
22
|
+
}): Promise<IApiResponse> {
|
|
23
|
+
const variant_ids = data.items.map(item => item.variant_id);
|
|
24
|
+
const response = await sendRequest({
|
|
25
|
+
url: `${process.env.NEXT_PUBLIC_API_URL}/api/sales/price-lists/evaluate`,
|
|
26
|
+
method: "POST",
|
|
27
|
+
data: {
|
|
28
|
+
party_id: data.party_id,
|
|
29
|
+
variant_ids
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return response.responseData as IApiResponse;
|
|
33
|
+
}
|
|
34
|
+
|
|
18
35
|
export async function bulkStockCheck(data: {
|
|
19
36
|
warehouse_id: number;
|
|
20
37
|
lines: Array<{ item_id: number; variant_id?: number | null; batch_id?: number | null; quantity: number }>;
|
package/src/constants/menus.ts
CHANGED
|
@@ -90,6 +90,7 @@ export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
|
90
90
|
{ key: 'core__terminals', label: 'Terminals', path: '/terminals', module: 'Core', defaultGroup: 'Resources', permission: 'terminal.view' },
|
|
91
91
|
{ key: 'core__currencies', label: 'Currencies', path: '/currencies', module: 'Core', defaultGroup: 'Resources', permission: 'currency.view' },
|
|
92
92
|
{ key: 'core__settings', label: 'Settings', path: '/settings', module: 'Core', defaultGroup: 'Configuration', permission: 'core_setting.view' },
|
|
93
|
+
{ key: 'core__approval_workflows', label: 'Approval Workflows', path: '/settings/approvals', module: 'Core', defaultGroup: 'Configuration', permission: null },
|
|
93
94
|
|
|
94
95
|
// ── Inventory Module ──
|
|
95
96
|
{ key: 'inventory__items', label: 'Items', path: '/inventory/items', module: 'Inventory', defaultGroup: 'Catalog', permission: null },
|
|
@@ -112,9 +113,9 @@ export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
|
112
113
|
{ key: 'sales__returns', label: 'Sales Returns', path: '/sales/returns', module: 'Sales', defaultGroup: 'Post-Sales', permission: null },
|
|
113
114
|
{ key: 'sales__credit_notes', label: 'Credit Notes', path: '/sales/credit-notes', module: 'Sales', defaultGroup: 'Post-Sales', permission: null },
|
|
114
115
|
{ key: 'sales__pos', label: 'POS Terminal', path: '/sales/pos', module: 'Sales', defaultGroup: 'POS', permission: null },
|
|
115
|
-
|
|
116
116
|
{ key: 'sales__pos_sessions', label: 'Terminal Sessions', path: '/sales/pos/sessions', module: 'Sales', defaultGroup: 'POS', permission: null },
|
|
117
117
|
{ key: 'sales__reports', label: 'Sales Reports', path: '/sales/reports', module: 'Sales', defaultGroup: 'Analytics', permission: null },
|
|
118
|
+
{ key: 'sales__settings', label: 'Settings', path: '/sales/settings', module: 'Sales', defaultGroup: 'Settings', permission: 'sales_setting.view' },
|
|
118
119
|
|
|
119
120
|
// ── Procurement Module ──
|
|
120
121
|
{ key: 'procurement__orders', label: 'Purchase Orders', path: '/procurement/orders', module: 'Procurement', defaultGroup: 'Orders', permission: null },
|
|
@@ -262,7 +263,7 @@ export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
|
262
263
|
{ key: 'construction__attendance', label: 'Attendance & Timesheets', path: '/construction/attendance', module: 'Construction', defaultGroup: 'Workforce', permission: null },
|
|
263
264
|
|
|
264
265
|
{ key: 'construction__equipment_types', label: 'Equipment Types', path: '/construction/equipment/types', module: 'Construction', defaultGroup: 'Equipment & Plant', permission: null },
|
|
265
|
-
{ key: 'construction__equipment', label: '
|
|
266
|
+
{ key: 'construction__equipment', label: 'Equipments', path: '/construction/equipment', module: 'Construction', defaultGroup: 'Equipment & Plant', permission: null },
|
|
266
267
|
{ key: 'construction__equipment_allocation', label: 'Equipment Allocation', path: '/construction/equipment/allocation', module: 'Construction', defaultGroup: 'Equipment & Plant', permission: null },
|
|
267
268
|
{ key: 'construction__fuel_logs', label: 'Fuel Logs', path: '/construction/equipment/fuel-logs', module: 'Construction', defaultGroup: 'Equipment & Plant', permission: null },
|
|
268
269
|
{ key: 'construction__maintenance', label: 'Maintenance', path: '/construction/equipment/maintenance', module: 'Construction', defaultGroup: 'Equipment & Plant', permission: null },
|
|
@@ -281,8 +282,8 @@ export const MENU_ITEM_REGISTRY: RegistryItem[] = [
|
|
|
281
282
|
{ key: 'construction__drawings', label: 'Drawing Register', path: '/construction/document-control/drawings', module: 'Construction', defaultGroup: 'Document Control', permission: null },
|
|
282
283
|
{ key: 'construction__rfis', label: 'RFIs', path: '/construction/document-control/rfis', module: 'Construction', defaultGroup: 'Document Control', permission: null },
|
|
283
284
|
|
|
284
|
-
{ key: 'construction__approval_workflows', label: 'Approval Workflows', path: '/construction/settings/approvals', module: 'Construction', defaultGroup: 'Configuration', permission: null },
|
|
285
285
|
{ key: 'construction__test_types', label: 'Test Types', path: '/construction/settings/test-types', module: 'Construction', defaultGroup: 'Configuration', permission: null },
|
|
286
|
+
{ key: 'construction__project_categories', label: 'Project Categories', path: '/construction/settings/project-categories', module: 'Construction', defaultGroup: 'Configuration', permission: 'project_category.view' },
|
|
286
287
|
{ key: 'construction__settings', label: 'Settings', path: '/construction/settings', module: 'Construction', defaultGroup: 'Configuration', permission: null },
|
|
287
288
|
|
|
288
289
|
// ── CRM Module ──
|
|
@@ -377,7 +378,7 @@ export const MENU_PRESETS: MenuPreset[] = [
|
|
|
377
378
|
'core__warehouses', 'core__terminals',
|
|
378
379
|
'core__activity_logs', 'core__api_requests', 'core__feature_access_logs',
|
|
379
380
|
'core__issue_logs', 'core__feature_registry', 'core__menu_config',
|
|
380
|
-
'core__printables', 'core__template_groups', 'core__currencies', 'core__settings',
|
|
381
|
+
'core__printables', 'core__template_groups', 'core__currencies', 'core__settings', 'core__approval_workflows',
|
|
381
382
|
],
|
|
382
383
|
},
|
|
383
384
|
{
|
|
@@ -399,6 +400,7 @@ export const MENU_PRESETS: MenuPreset[] = [
|
|
|
399
400
|
'sales__quotations', 'sales__orders', 'sales__goods_issue_notes',
|
|
400
401
|
'sales__returns', 'sales__credit_notes',
|
|
401
402
|
'sales__pos', 'sales__pos_sessions',
|
|
403
|
+
'sales__settings'
|
|
402
404
|
],
|
|
403
405
|
},
|
|
404
406
|
{
|
|
@@ -540,8 +542,8 @@ export const MENU_PRESETS: MenuPreset[] = [
|
|
|
540
542
|
'construction__material_testing',
|
|
541
543
|
'construction__safety_incidents',
|
|
542
544
|
'construction__ptw',
|
|
543
|
-
'construction__approval_workflows',
|
|
544
545
|
'construction__test_types',
|
|
546
|
+
'construction__project_categories',
|
|
545
547
|
'construction__settings',
|
|
546
548
|
],
|
|
547
549
|
},
|
package/src/index.ts
CHANGED
|
@@ -9,4 +9,5 @@ export * from './api-services/inventory/brands.client';
|
|
|
9
9
|
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
|
-
export * from './api-services/inventory/transaction.client';
|
|
12
|
+
export * from './api-services/inventory/transaction.client';
|
|
13
|
+
export * from './utils/PriceCalculationService';
|
|
@@ -3,7 +3,8 @@ import { z } from "zod";
|
|
|
3
3
|
export const approvalStepSchema = z.object({
|
|
4
4
|
step_order: z.number().int().positive(),
|
|
5
5
|
approver_type: z.enum(["user", "role"]),
|
|
6
|
-
|
|
6
|
+
approver_ids: z.array(z.string()).min(1, "At least one approver is required"),
|
|
7
|
+
required_approvals: z.number().int().min(1, "Must be at least 1")
|
|
7
8
|
});
|
|
8
9
|
|
|
9
10
|
export const approvalWorkflowSchema = z.object({
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface IPricingRule {
|
|
2
|
+
id: number;
|
|
3
|
+
price_list_name?: string;
|
|
4
|
+
min_quantity: number;
|
|
5
|
+
rate: number | null;
|
|
6
|
+
markdown_percentage: number | null;
|
|
7
|
+
final_rate?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class PriceCalculationService {
|
|
11
|
+
/**
|
|
12
|
+
* Calculate detailed price breakdown for a given quantity using pricing rules
|
|
13
|
+
*/
|
|
14
|
+
public static calculatePriceDetails(
|
|
15
|
+
basePrice: number,
|
|
16
|
+
quantity: number,
|
|
17
|
+
rules?: IPricingRule[]
|
|
18
|
+
): { unitPrice: number; discountPercent: number; discountAmount: number; appliedRule?: IPricingRule } {
|
|
19
|
+
if (!rules || rules.length === 0) {
|
|
20
|
+
return { unitPrice: basePrice, discountPercent: 0, discountAmount: 0 };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Filter rules that match the quantity condition
|
|
24
|
+
const applicableRules = rules.filter(r => quantity >= r.min_quantity);
|
|
25
|
+
|
|
26
|
+
if (applicableRules.length === 0) {
|
|
27
|
+
return { unitPrice: basePrice, discountPercent: 0, discountAmount: 0 };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Sort by min_quantity descending (highest threshold wins)
|
|
31
|
+
applicableRules.sort((a, b) => b.min_quantity - a.min_quantity);
|
|
32
|
+
|
|
33
|
+
const activeRule = applicableRules[0];
|
|
34
|
+
|
|
35
|
+
if (activeRule.rate !== null && activeRule.rate !== undefined) {
|
|
36
|
+
return { unitPrice: activeRule.rate, discountPercent: 0, discountAmount: 0, appliedRule: { ...activeRule, final_rate: activeRule.rate } };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (activeRule.markdown_percentage !== null && activeRule.markdown_percentage !== undefined) {
|
|
40
|
+
const markdownAmount = basePrice * (activeRule.markdown_percentage / 100);
|
|
41
|
+
const newUnitPrice = basePrice - markdownAmount;
|
|
42
|
+
return { unitPrice: newUnitPrice, discountPercent: 0, discountAmount: 0, appliedRule: { ...activeRule, final_rate: newUnitPrice } };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { unitPrice: basePrice, discountPercent: 0, discountAmount: 0 };
|
|
46
|
+
}
|
|
47
|
+
}
|