@open-mercato/core 0.4.2-canary-5d2c419a9b → 0.4.2-canary-9e0237de8e
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/dist/generated/entities/workflow_event_trigger/index.js +33 -0
- package/dist/generated/entities/workflow_event_trigger/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/auth/events.js +30 -0
- package/dist/modules/auth/events.js.map +7 -0
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js +145 -0
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js.map +7 -0
- package/dist/modules/business_rules/data/validators.js +34 -0
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/index.js +21 -1
- package/dist/modules/business_rules/index.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +182 -1
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/events.js +34 -0
- package/dist/modules/catalog/events.js.map +7 -0
- package/dist/modules/customers/events.js +49 -0
- package/dist/modules/customers/events.js.map +7 -0
- package/dist/modules/directory/events.js +23 -0
- package/dist/modules/directory/events.js.map +7 -0
- package/dist/modules/sales/acl.js +1 -0
- package/dist/modules/sales/acl.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +12 -0
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +62 -0
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/events.js +63 -0
- package/dist/modules/sales/events.js.map +7 -0
- package/dist/modules/sales/lib/dictionaries.js +3 -0
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/sales/lib/frontend/documentDataEvents.js +25 -0
- package/dist/modules/sales/lib/frontend/documentDataEvents.js.map +7 -0
- package/dist/modules/workflows/acl.js +2 -0
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +18 -6
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +6 -1
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +9 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +24 -15
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +150 -132
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +5 -6
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +81 -3
- package/dist/modules/workflows/cli.js.map +3 -3
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +481 -0
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +7 -0
- package/dist/modules/workflows/components/EventTriggersEditor.js +553 -0
- package/dist/modules/workflows/components/EventTriggersEditor.js.map +7 -0
- package/dist/modules/workflows/data/entities.js +64 -1
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +115 -0
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/events.js +38 -0
- package/dist/modules/workflows/events.js.map +7 -0
- package/dist/modules/workflows/examples/checkout-demo-definition.json +1 -5
- package/dist/modules/workflows/examples/order-approval-definition.json +257 -0
- package/dist/modules/workflows/examples/order-approval-guard-rules.json +32 -0
- package/dist/modules/workflows/lib/activity-executor.js +75 -13
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/event-trigger-service.js +308 -0
- package/dist/modules/workflows/lib/event-trigger-service.js.map +7 -0
- package/dist/modules/workflows/lib/graph-utils.js +71 -2
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +17 -4
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +33 -23
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +157 -45
- package/dist/modules/workflows/lib/transition-handler.js.map +3 -3
- package/dist/modules/workflows/migrations/Migration20260123143500.js +36 -0
- package/dist/modules/workflows/migrations/Migration20260123143500.js.map +7 -0
- package/dist/modules/workflows/subscribers/event-trigger.js +78 -0
- package/dist/modules/workflows/subscribers/event-trigger.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +323 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +7 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js +17 -0
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js.map +7 -0
- package/dist/modules/workflows/widgets/injection-table.js +19 -0
- package/dist/modules/workflows/widgets/injection-table.js.map +7 -0
- package/generated/entities/workflow_event_trigger/index.ts +15 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +2 -2
- package/src/modules/auth/events.ts +39 -0
- package/src/modules/business_rules/api/execute/[ruleId]/route.ts +163 -0
- package/src/modules/business_rules/data/validators.ts +40 -0
- package/src/modules/business_rules/index.ts +25 -0
- package/src/modules/business_rules/lib/rule-engine.ts +281 -1
- package/src/modules/catalog/events.ts +45 -0
- package/src/modules/customers/events.ts +63 -0
- package/src/modules/directory/events.ts +31 -0
- package/src/modules/sales/acl.ts +1 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +16 -0
- package/src/modules/sales/commands/documents.ts +75 -1
- package/src/modules/sales/events.ts +82 -0
- package/src/modules/sales/lib/dictionaries.ts +3 -0
- package/src/modules/sales/lib/frontend/documentDataEvents.ts +28 -0
- package/src/modules/workflows/acl.ts +2 -0
- package/src/modules/workflows/api/__tests__/instances.route.test.ts +5 -2
- package/src/modules/workflows/api/instances/route.ts +21 -7
- package/src/modules/workflows/api/tasks/route.ts +7 -1
- package/src/modules/workflows/backend/definitions/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +9 -0
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +9 -0
- package/src/modules/workflows/backend/definitions/visual-editor/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +21 -3
- package/src/modules/workflows/backend/events/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/events/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/instances/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/tasks/page.tsx +5 -6
- package/src/modules/workflows/cli.ts +111 -0
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +581 -0
- package/src/modules/workflows/components/EventTriggersEditor.tsx +664 -0
- package/src/modules/workflows/data/entities.ts +124 -0
- package/src/modules/workflows/data/validators.ts +138 -0
- package/src/modules/workflows/events.ts +49 -0
- package/src/modules/workflows/examples/checkout-demo-definition.json +1 -5
- package/src/modules/workflows/examples/order-approval-definition.json +257 -0
- package/src/modules/workflows/examples/order-approval-guard-rules.json +32 -0
- package/src/modules/workflows/i18n/en.json +71 -0
- package/src/modules/workflows/lib/__tests__/activity-executor.test.ts +43 -36
- package/src/modules/workflows/lib/__tests__/transition-handler.test.ts +170 -90
- package/src/modules/workflows/lib/activity-executor.ts +129 -16
- package/src/modules/workflows/lib/event-trigger-service.ts +557 -0
- package/src/modules/workflows/lib/graph-utils.ts +117 -2
- package/src/modules/workflows/lib/seeds.ts +29 -8
- package/src/modules/workflows/lib/start-validator.ts +38 -28
- package/src/modules/workflows/lib/transition-handler.ts +208 -55
- package/src/modules/workflows/migrations/Migration20260123143500.ts +38 -0
- package/src/modules/workflows/subscribers/event-trigger.ts +109 -0
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +446 -0
- package/src/modules/workflows/widgets/injection/order-approval/widget.ts +16 -0
- package/src/modules/workflows/widgets/injection-table.ts +21 -0
|
@@ -161,6 +161,7 @@
|
|
|
161
161
|
"title": "Workflow Instances",
|
|
162
162
|
"singular": "Workflow Instance",
|
|
163
163
|
"plural": "Workflow Instances",
|
|
164
|
+
"duration": "Duration",
|
|
164
165
|
"fields": {
|
|
165
166
|
"instanceId": "Instance ID",
|
|
166
167
|
"workflowId": "Workflow ID",
|
|
@@ -563,6 +564,55 @@
|
|
|
563
564
|
"CompensationCompleted": "Compensation Completed"
|
|
564
565
|
}
|
|
565
566
|
},
|
|
567
|
+
"triggers": {
|
|
568
|
+
"title": "Event Triggers",
|
|
569
|
+
"add": "Add Trigger",
|
|
570
|
+
"description": "Configure events that automatically start this workflow. When a matching event occurs in the system, a new workflow instance will be created with the mapped context.",
|
|
571
|
+
"empty": {
|
|
572
|
+
"title": "No triggers configured",
|
|
573
|
+
"description": "Click \"Add Trigger\" to create an event trigger that automatically starts this workflow."
|
|
574
|
+
},
|
|
575
|
+
"dialog": {
|
|
576
|
+
"create": {
|
|
577
|
+
"title": "Create Event Trigger"
|
|
578
|
+
},
|
|
579
|
+
"edit": {
|
|
580
|
+
"title": "Edit Event Trigger"
|
|
581
|
+
},
|
|
582
|
+
"description": "Configure when this workflow should be automatically started based on system events."
|
|
583
|
+
},
|
|
584
|
+
"delete": {
|
|
585
|
+
"title": "Delete Event Trigger?",
|
|
586
|
+
"description": "This will remove the event trigger. The change will take effect when you save the workflow definition."
|
|
587
|
+
},
|
|
588
|
+
"fields": {
|
|
589
|
+
"name": "Name",
|
|
590
|
+
"description": "Description",
|
|
591
|
+
"eventPattern": "Event Pattern",
|
|
592
|
+
"enabled": "Enabled",
|
|
593
|
+
"priority": "Priority",
|
|
594
|
+
"filterConditions": "Filter Conditions",
|
|
595
|
+
"contextMapping": "Context Mapping",
|
|
596
|
+
"debounceMs": "Debounce (ms)",
|
|
597
|
+
"maxConcurrent": "Max Concurrent Instances"
|
|
598
|
+
},
|
|
599
|
+
"placeholders": {
|
|
600
|
+
"name": "Order Created Trigger",
|
|
601
|
+
"description": "Describe when this trigger should fire...",
|
|
602
|
+
"quickSelect": "Quick select...",
|
|
603
|
+
"unlimited": "Unlimited"
|
|
604
|
+
},
|
|
605
|
+
"hints": {
|
|
606
|
+
"priority": "Higher priority triggers execute first",
|
|
607
|
+
"eventPattern": "Use * as wildcard: \"sales.orders.*\" matches any order event",
|
|
608
|
+
"filterConditions": "Only trigger when the event payload matches these conditions (all must match)",
|
|
609
|
+
"contextMapping": "Map values from the event payload to the workflow's initial context",
|
|
610
|
+
"debounce": "Delay to prevent rapid re-triggers",
|
|
611
|
+
"maxConcurrent": "Limit simultaneous workflow instances"
|
|
612
|
+
},
|
|
613
|
+
"addCondition": "Add Condition",
|
|
614
|
+
"addMapping": "Add Mapping"
|
|
615
|
+
},
|
|
566
616
|
"common": {
|
|
567
617
|
"save": "Save",
|
|
568
618
|
"cancel": "Cancel",
|
|
@@ -629,6 +679,27 @@
|
|
|
629
679
|
"duplicateNotYetImplemented": "Duplicate functionality is not yet implemented"
|
|
630
680
|
}
|
|
631
681
|
},
|
|
682
|
+
"orderApproval": {
|
|
683
|
+
"groupLabel": "Order Approval",
|
|
684
|
+
"groupDescription": "Review and approve or reject this order",
|
|
685
|
+
"pendingTitle": "Pending Approval",
|
|
686
|
+
"pendingDescription": "This order requires approval before processing",
|
|
687
|
+
"decisionLabel": "Decision",
|
|
688
|
+
"approveButton": "Approve",
|
|
689
|
+
"rejectButton": "Reject",
|
|
690
|
+
"commentsLabel": "Comments",
|
|
691
|
+
"commentsPlaceholder": "Add optional comments...",
|
|
692
|
+
"approvedStatus": "Approved",
|
|
693
|
+
"rejectedStatus": "Rejected",
|
|
694
|
+
"requestApproval": "Request Approval",
|
|
695
|
+
"submitDecision": "Submit Decision",
|
|
696
|
+
"noWorkflowActive": "No approval workflow is active for this order.",
|
|
697
|
+
"processing": "Workflow is processing...",
|
|
698
|
+
"completed": "Approval workflow completed.",
|
|
699
|
+
"startError": "Failed to start approval workflow",
|
|
700
|
+
"completeError": "Failed to complete approval task",
|
|
701
|
+
"missingStatuses": "Missing order status entries. Please ensure pending_approval, approved, and rejected statuses exist in the sales.order_status dictionary."
|
|
702
|
+
},
|
|
632
703
|
"common": {
|
|
633
704
|
"all": "All",
|
|
634
705
|
"enabled": "Enabled",
|
|
@@ -318,22 +318,24 @@ describe('Activity Executor (Unit Tests)', () => {
|
|
|
318
318
|
|
|
319
319
|
describe('UPDATE_ENTITY activity', () => {
|
|
320
320
|
test('should execute UPDATE_ENTITY activity successfully', async () => {
|
|
321
|
-
const
|
|
322
|
-
|
|
321
|
+
const mockCommandBus = {
|
|
322
|
+
execute: jest.fn().mockResolvedValue({
|
|
323
|
+
result: { id: 'order-123', status: 'confirmed' },
|
|
324
|
+
logEntry: { id: 'log-123' },
|
|
325
|
+
}),
|
|
323
326
|
}
|
|
324
327
|
|
|
325
|
-
mockContainer.resolve.mockReturnValue(
|
|
328
|
+
mockContainer.resolve.mockReturnValue(mockCommandBus)
|
|
326
329
|
|
|
327
330
|
const activity: ActivityDefinition = {
|
|
328
331
|
activityId: 'activity-8',
|
|
329
332
|
activityName: 'Update Order Status',
|
|
330
333
|
activityType: 'UPDATE_ENTITY',
|
|
331
334
|
config: {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
confirmedAt: new Date().toISOString(),
|
|
335
|
+
commandId: 'sales.orders.update',
|
|
336
|
+
input: {
|
|
337
|
+
id: 'order-123',
|
|
338
|
+
statusEntryId: 'status-confirmed-id',
|
|
337
339
|
},
|
|
338
340
|
},
|
|
339
341
|
}
|
|
@@ -346,21 +348,22 @@ describe('Activity Executor (Unit Tests)', () => {
|
|
|
346
348
|
)
|
|
347
349
|
|
|
348
350
|
expect(result.success).toBe(true)
|
|
349
|
-
expect(result.output.
|
|
350
|
-
expect(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
351
|
+
expect(result.output.executed).toBe(true)
|
|
352
|
+
expect(result.output.commandId).toBe('sales.orders.update')
|
|
353
|
+
expect(mockCommandBus.execute).toHaveBeenCalledWith(
|
|
354
|
+
'sales.orders.update',
|
|
355
|
+
expect.objectContaining({
|
|
356
|
+
input: expect.objectContaining({
|
|
357
|
+
id: 'order-123',
|
|
358
|
+
statusEntryId: 'status-confirmed-id',
|
|
359
|
+
}),
|
|
360
|
+
})
|
|
361
|
+
)
|
|
359
362
|
})
|
|
360
363
|
|
|
361
|
-
test('should fail UPDATE_ENTITY if
|
|
364
|
+
test('should fail UPDATE_ENTITY if command bus not available', async () => {
|
|
362
365
|
mockContainer.resolve.mockImplementation(() => {
|
|
363
|
-
throw new Error('
|
|
366
|
+
throw new Error('commandBus not registered')
|
|
364
367
|
})
|
|
365
368
|
|
|
366
369
|
const activity: ActivityDefinition = {
|
|
@@ -368,9 +371,8 @@ describe('Activity Executor (Unit Tests)', () => {
|
|
|
368
371
|
activityName: 'Test Update',
|
|
369
372
|
activityType: 'UPDATE_ENTITY',
|
|
370
373
|
config: {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
updates: { status: 'confirmed' },
|
|
374
|
+
commandId: 'sales.orders.update',
|
|
375
|
+
input: { id: 'order-123', status: 'confirmed' },
|
|
374
376
|
},
|
|
375
377
|
}
|
|
376
378
|
|
|
@@ -382,23 +384,23 @@ describe('Activity Executor (Unit Tests)', () => {
|
|
|
382
384
|
)
|
|
383
385
|
|
|
384
386
|
expect(result.success).toBe(false)
|
|
385
|
-
expect(result.error).toContain('
|
|
387
|
+
expect(result.error).toContain('commandBus not registered')
|
|
386
388
|
})
|
|
387
389
|
|
|
388
390
|
test('should fail UPDATE_ENTITY if missing required fields', async () => {
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
+
const mockCommandBus = {
|
|
392
|
+
execute: jest.fn().mockResolvedValue({ result: {} }),
|
|
391
393
|
}
|
|
392
394
|
|
|
393
|
-
mockContainer.resolve.mockReturnValue(
|
|
395
|
+
mockContainer.resolve.mockReturnValue(mockCommandBus)
|
|
394
396
|
|
|
395
397
|
const activity: ActivityDefinition = {
|
|
396
398
|
activityId: 'activity-10',
|
|
397
399
|
activityName: 'Invalid Update',
|
|
398
400
|
activityType: 'UPDATE_ENTITY',
|
|
399
401
|
config: {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
+
// Missing commandId
|
|
403
|
+
input: { id: 'order-123' },
|
|
402
404
|
},
|
|
403
405
|
}
|
|
404
406
|
|
|
@@ -410,7 +412,7 @@ describe('Activity Executor (Unit Tests)', () => {
|
|
|
410
412
|
)
|
|
411
413
|
|
|
412
414
|
expect(result.success).toBe(false)
|
|
413
|
-
expect(result.error).toContain('requires "
|
|
415
|
+
expect(result.error).toContain('requires "commandId"')
|
|
414
416
|
})
|
|
415
417
|
})
|
|
416
418
|
|
|
@@ -1095,13 +1097,16 @@ describe('Activity Executor (Unit Tests)', () => {
|
|
|
1095
1097
|
emitEvent: jest.fn().mockResolvedValue(undefined),
|
|
1096
1098
|
}
|
|
1097
1099
|
|
|
1098
|
-
const
|
|
1099
|
-
|
|
1100
|
+
const mockCommandBus = {
|
|
1101
|
+
execute: jest.fn().mockResolvedValue({
|
|
1102
|
+
result: { id: 'order-123', status: 'confirmed' },
|
|
1103
|
+
logEntry: { id: 'log-123' },
|
|
1104
|
+
}),
|
|
1100
1105
|
}
|
|
1101
1106
|
|
|
1102
1107
|
mockContainer.resolve
|
|
1103
1108
|
.mockReturnValueOnce(mockEventBus) // First activity
|
|
1104
|
-
.mockReturnValueOnce(
|
|
1109
|
+
.mockReturnValueOnce(mockCommandBus) // Second activity
|
|
1105
1110
|
|
|
1106
1111
|
const activities: ActivityDefinition[] = [
|
|
1107
1112
|
{
|
|
@@ -1118,9 +1123,11 @@ describe('Activity Executor (Unit Tests)', () => {
|
|
|
1118
1123
|
activityName: 'Update Entity',
|
|
1119
1124
|
activityType: 'UPDATE_ENTITY',
|
|
1120
1125
|
config: {
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1126
|
+
commandId: 'sales.orders.update',
|
|
1127
|
+
input: {
|
|
1128
|
+
id: 'order-123',
|
|
1129
|
+
statusEntryId: 'status-confirmed-id',
|
|
1130
|
+
},
|
|
1124
1131
|
},
|
|
1125
1132
|
},
|
|
1126
1133
|
]
|
|
@@ -462,15 +462,35 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
462
462
|
})
|
|
463
463
|
|
|
464
464
|
test('should reject transition if pre-conditions fail', async () => {
|
|
465
|
+
// Create a definition with preConditions
|
|
466
|
+
const definitionWithPreConditions = {
|
|
467
|
+
...mockDefinition,
|
|
468
|
+
definition: {
|
|
469
|
+
...mockDefinition.definition,
|
|
470
|
+
transitions: [
|
|
471
|
+
{ fromStepId: 'start', toStepId: 'step-1' },
|
|
472
|
+
{
|
|
473
|
+
fromStepId: 'step-1',
|
|
474
|
+
toStepId: 'step-2',
|
|
475
|
+
preConditions: [{ ruleId: 'test-guard-rule', required: true }],
|
|
476
|
+
},
|
|
477
|
+
{ fromStepId: 'step-2', toStepId: 'end' },
|
|
478
|
+
],
|
|
479
|
+
},
|
|
480
|
+
}
|
|
481
|
+
|
|
465
482
|
mockEm.findOne
|
|
466
|
-
.mockResolvedValueOnce(
|
|
467
|
-
.mockResolvedValueOnce(
|
|
468
|
-
|
|
469
|
-
;(ruleEngine.
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
483
|
+
.mockResolvedValueOnce(definitionWithPreConditions) // evaluateTransition
|
|
484
|
+
.mockResolvedValueOnce(definitionWithPreConditions) // evaluatePreConditions
|
|
485
|
+
|
|
486
|
+
;(ruleEngine.executeRuleByRuleId as jest.Mock).mockResolvedValueOnce({
|
|
487
|
+
success: false,
|
|
488
|
+
ruleId: 'test-guard-rule',
|
|
489
|
+
ruleName: 'Test Guard Rule',
|
|
490
|
+
conditionResult: false,
|
|
491
|
+
actionsExecuted: null,
|
|
492
|
+
executionTime: 10,
|
|
493
|
+
error: undefined,
|
|
474
494
|
})
|
|
475
495
|
|
|
476
496
|
mockEm.create.mockReturnValue({} as any)
|
|
@@ -491,15 +511,35 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
491
511
|
})
|
|
492
512
|
|
|
493
513
|
test('should log transition rejection event', async () => {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
514
|
+
// Create a definition with preConditions
|
|
515
|
+
const definitionWithPreConditions = {
|
|
516
|
+
...mockDefinition,
|
|
517
|
+
definition: {
|
|
518
|
+
...mockDefinition.definition,
|
|
519
|
+
transitions: [
|
|
520
|
+
{ fromStepId: 'start', toStepId: 'step-1' },
|
|
521
|
+
{
|
|
522
|
+
fromStepId: 'step-1',
|
|
523
|
+
toStepId: 'step-2',
|
|
524
|
+
preConditions: [{ ruleId: 'test-guard-rule', required: true }],
|
|
525
|
+
},
|
|
526
|
+
{ fromStepId: 'step-2', toStepId: 'end' },
|
|
527
|
+
],
|
|
528
|
+
},
|
|
529
|
+
}
|
|
497
530
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
531
|
+
mockEm.findOne
|
|
532
|
+
.mockResolvedValueOnce(definitionWithPreConditions)
|
|
533
|
+
.mockResolvedValueOnce(definitionWithPreConditions)
|
|
534
|
+
|
|
535
|
+
;(ruleEngine.executeRuleByRuleId as jest.Mock).mockResolvedValueOnce({
|
|
536
|
+
success: false,
|
|
537
|
+
ruleId: 'test-guard-rule',
|
|
538
|
+
ruleName: 'Test Guard Rule',
|
|
539
|
+
conditionResult: false,
|
|
540
|
+
actionsExecuted: null,
|
|
541
|
+
executionTime: 10,
|
|
542
|
+
error: undefined,
|
|
503
543
|
})
|
|
504
544
|
|
|
505
545
|
mockEm.create.mockReturnValue({} as any)
|
|
@@ -527,27 +567,36 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
527
567
|
})
|
|
528
568
|
|
|
529
569
|
test('should execute transition even if post-conditions fail (warning only)', async () => {
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
570
|
+
// Create a definition with postConditions
|
|
571
|
+
const definitionWithPostConditions = {
|
|
572
|
+
...mockDefinition,
|
|
573
|
+
definition: {
|
|
574
|
+
...mockDefinition.definition,
|
|
575
|
+
transitions: [
|
|
576
|
+
{ fromStepId: 'start', toStepId: 'step-1' },
|
|
577
|
+
{
|
|
578
|
+
fromStepId: 'step-1',
|
|
579
|
+
toStepId: 'step-2',
|
|
580
|
+
postConditions: [{ ruleId: 'test-post-rule', required: true }],
|
|
581
|
+
},
|
|
582
|
+
{ fromStepId: 'step-2', toStepId: 'end' },
|
|
583
|
+
],
|
|
584
|
+
},
|
|
585
|
+
}
|
|
538
586
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
587
|
+
mockEm.findOne.mockReset()
|
|
588
|
+
mockEm.findOne.mockResolvedValue(definitionWithPostConditions)
|
|
589
|
+
|
|
590
|
+
// Post-condition fails
|
|
591
|
+
;(ruleEngine.executeRuleByRuleId as jest.Mock).mockResolvedValueOnce({
|
|
592
|
+
success: false,
|
|
593
|
+
ruleId: 'test-post-rule',
|
|
594
|
+
ruleName: 'Test Post Rule',
|
|
595
|
+
conditionResult: false,
|
|
596
|
+
actionsExecuted: null,
|
|
597
|
+
executionTime: 5,
|
|
598
|
+
error: undefined,
|
|
599
|
+
})
|
|
551
600
|
|
|
552
601
|
mockEm.create.mockReturnValue({} as any)
|
|
553
602
|
|
|
@@ -709,22 +758,33 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
709
758
|
|
|
710
759
|
describe('Business Rules Integration', () => {
|
|
711
760
|
test('should call rule engine for pre-conditions with correct entityType', async () => {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
761
|
+
// Create a definition with preConditions
|
|
762
|
+
const definitionWithPreConditions = {
|
|
763
|
+
...mockDefinition,
|
|
764
|
+
definition: {
|
|
765
|
+
...mockDefinition.definition,
|
|
766
|
+
transitions: [
|
|
767
|
+
{ fromStepId: 'start', toStepId: 'step-1' },
|
|
768
|
+
{
|
|
769
|
+
fromStepId: 'step-1',
|
|
770
|
+
toStepId: 'step-2',
|
|
771
|
+
preConditions: [{ ruleId: 'test-guard-rule', required: true }],
|
|
772
|
+
},
|
|
773
|
+
{ fromStepId: 'step-2', toStepId: 'end' },
|
|
774
|
+
],
|
|
775
|
+
},
|
|
776
|
+
}
|
|
716
777
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
})
|
|
778
|
+
mockEm.findOne.mockResolvedValue(definitionWithPreConditions)
|
|
779
|
+
|
|
780
|
+
;(ruleEngine.executeRuleByRuleId as jest.Mock).mockResolvedValueOnce({
|
|
781
|
+
success: true,
|
|
782
|
+
ruleId: 'test-guard-rule',
|
|
783
|
+
ruleName: 'Test Guard Rule',
|
|
784
|
+
conditionResult: true,
|
|
785
|
+
actionsExecuted: null,
|
|
786
|
+
executionTime: 10,
|
|
787
|
+
})
|
|
728
788
|
|
|
729
789
|
mockEm.create.mockReturnValue({} as any)
|
|
730
790
|
|
|
@@ -737,9 +797,10 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
737
797
|
{ workflowContext: {} }
|
|
738
798
|
)
|
|
739
799
|
|
|
740
|
-
expect(ruleEngine.
|
|
800
|
+
expect(ruleEngine.executeRuleByRuleId).toHaveBeenCalledWith(
|
|
741
801
|
mockEm,
|
|
742
802
|
expect.objectContaining({
|
|
803
|
+
ruleId: 'test-guard-rule',
|
|
743
804
|
entityType: 'workflow:simple-approval:transition',
|
|
744
805
|
eventType: 'pre_transition',
|
|
745
806
|
data: expect.objectContaining({
|
|
@@ -752,26 +813,34 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
752
813
|
})
|
|
753
814
|
|
|
754
815
|
test('should call rule engine for post-conditions with correct eventType', async () => {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
816
|
+
// Create a definition with postConditions
|
|
817
|
+
const definitionWithPostConditions = {
|
|
818
|
+
...mockDefinition,
|
|
819
|
+
definition: {
|
|
820
|
+
...mockDefinition.definition,
|
|
821
|
+
transitions: [
|
|
822
|
+
{ fromStepId: 'start', toStepId: 'step-1' },
|
|
823
|
+
{
|
|
824
|
+
fromStepId: 'step-1',
|
|
825
|
+
toStepId: 'step-2',
|
|
826
|
+
postConditions: [{ ruleId: 'test-post-rule', required: true }],
|
|
827
|
+
},
|
|
828
|
+
{ fromStepId: 'step-2', toStepId: 'end' },
|
|
829
|
+
],
|
|
830
|
+
},
|
|
831
|
+
}
|
|
763
832
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
833
|
+
mockEm.findOne.mockReset()
|
|
834
|
+
mockEm.findOne.mockResolvedValue(definitionWithPostConditions)
|
|
835
|
+
|
|
836
|
+
;(ruleEngine.executeRuleByRuleId as jest.Mock).mockResolvedValueOnce({
|
|
837
|
+
success: true,
|
|
838
|
+
ruleId: 'test-post-rule',
|
|
839
|
+
ruleName: 'Test Post Rule',
|
|
840
|
+
conditionResult: true,
|
|
841
|
+
actionsExecuted: null,
|
|
842
|
+
executionTime: 5,
|
|
843
|
+
})
|
|
775
844
|
|
|
776
845
|
mockEm.create.mockReturnValue({} as any)
|
|
777
846
|
|
|
@@ -784,11 +853,11 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
784
853
|
{ workflowContext: {} }
|
|
785
854
|
)
|
|
786
855
|
|
|
787
|
-
// Check
|
|
788
|
-
expect(ruleEngine.
|
|
789
|
-
2,
|
|
856
|
+
// Check call to executeRuleByRuleId for post-conditions
|
|
857
|
+
expect(ruleEngine.executeRuleByRuleId).toHaveBeenCalledWith(
|
|
790
858
|
mockEm,
|
|
791
859
|
expect.objectContaining({
|
|
860
|
+
ruleId: 'test-post-rule',
|
|
792
861
|
entityType: 'workflow:simple-approval:transition',
|
|
793
862
|
eventType: 'post_transition',
|
|
794
863
|
}),
|
|
@@ -797,22 +866,33 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
797
866
|
})
|
|
798
867
|
|
|
799
868
|
test('should pass workflow context and trigger data to rule engine', async () => {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
869
|
+
// Create a definition with preConditions
|
|
870
|
+
const definitionWithPreConditions = {
|
|
871
|
+
...mockDefinition,
|
|
872
|
+
definition: {
|
|
873
|
+
...mockDefinition.definition,
|
|
874
|
+
transitions: [
|
|
875
|
+
{ fromStepId: 'start', toStepId: 'step-1' },
|
|
876
|
+
{
|
|
877
|
+
fromStepId: 'step-1',
|
|
878
|
+
toStepId: 'step-2',
|
|
879
|
+
preConditions: [{ ruleId: 'test-guard-rule', required: true }],
|
|
880
|
+
},
|
|
881
|
+
{ fromStepId: 'step-2', toStepId: 'end' },
|
|
882
|
+
],
|
|
883
|
+
},
|
|
884
|
+
}
|
|
804
885
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
})
|
|
886
|
+
mockEm.findOne.mockResolvedValue(definitionWithPreConditions)
|
|
887
|
+
|
|
888
|
+
;(ruleEngine.executeRuleByRuleId as jest.Mock).mockResolvedValueOnce({
|
|
889
|
+
success: true,
|
|
890
|
+
ruleId: 'test-guard-rule',
|
|
891
|
+
ruleName: 'Test Guard Rule',
|
|
892
|
+
conditionResult: true,
|
|
893
|
+
actionsExecuted: null,
|
|
894
|
+
executionTime: 10,
|
|
895
|
+
})
|
|
816
896
|
|
|
817
897
|
mockEm.create.mockReturnValue({} as any)
|
|
818
898
|
|
|
@@ -832,7 +912,7 @@ describe('Transition Handler (Unit Tests)', () => {
|
|
|
832
912
|
}
|
|
833
913
|
)
|
|
834
914
|
|
|
835
|
-
expect(ruleEngine.
|
|
915
|
+
expect(ruleEngine.executeRuleByRuleId).toHaveBeenCalledWith(
|
|
836
916
|
mockEm,
|
|
837
917
|
expect.objectContaining({
|
|
838
918
|
data: expect.objectContaining({
|