@open-mercato/core 0.4.2-canary-d0a025141f → 0.4.2-canary-3efa759f5c
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.ids.generated.js +0 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/business_rules/data/validators.js +0 -34
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/index.js +1 -21
- package/dist/modules/business_rules/index.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +1 -182
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/sales/acl.js +0 -1
- package/dist/modules/sales/acl.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +0 -12
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -62
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +0 -3
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/workflows/acl.js +0 -2
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +6 -18
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +1 -6
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +1 -9
- 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 +15 -24
- 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 +132 -150
- 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 +6 -5
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +3 -81
- package/dist/modules/workflows/cli.js.map +3 -3
- package/dist/modules/workflows/data/entities.js +1 -64
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +0 -115
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/dist/modules/workflows/lib/activity-executor.js +13 -75
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/graph-utils.js +2 -71
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +5 -22
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +23 -33
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +45 -157
- package/dist/modules/workflows/lib/transition-handler.js.map +3 -3
- package/generated/entities.ids.generated.ts +0 -1
- package/generated/entity-fields-registry.ts +0 -2
- package/package.json +2 -2
- package/src/modules/business_rules/data/validators.ts +0 -40
- package/src/modules/business_rules/index.ts +0 -25
- package/src/modules/business_rules/lib/rule-engine.ts +1 -281
- package/src/modules/sales/acl.ts +0 -1
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +0 -16
- package/src/modules/sales/commands/documents.ts +1 -74
- package/src/modules/sales/lib/dictionaries.ts +0 -3
- package/src/modules/workflows/acl.ts +0 -2
- package/src/modules/workflows/api/__tests__/instances.route.test.ts +2 -5
- package/src/modules/workflows/api/instances/route.ts +7 -21
- package/src/modules/workflows/api/tasks/route.ts +1 -7
- package/src/modules/workflows/backend/definitions/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/visual-editor/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3 -21
- 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 +6 -5
- package/src/modules/workflows/cli.ts +0 -111
- package/src/modules/workflows/data/entities.ts +0 -124
- package/src/modules/workflows/data/validators.ts +0 -138
- package/src/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/src/modules/workflows/i18n/en.json +0 -71
- package/src/modules/workflows/lib/__tests__/activity-executor.test.ts +36 -43
- package/src/modules/workflows/lib/__tests__/transition-handler.test.ts +90 -170
- package/src/modules/workflows/lib/activity-executor.ts +16 -129
- package/src/modules/workflows/lib/graph-utils.ts +2 -117
- package/src/modules/workflows/lib/seeds.ts +8 -34
- package/src/modules/workflows/lib/start-validator.ts +28 -38
- package/src/modules/workflows/lib/transition-handler.ts +55 -208
- package/dist/generated/entities/workflow_event_trigger/index.js +0 -33
- package/dist/generated/entities/workflow_event_trigger/index.js.map +0 -7
- package/dist/modules/auth/events.js +0 -30
- package/dist/modules/auth/events.js.map +0 -7
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js +0 -145
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js.map +0 -7
- package/dist/modules/catalog/events.js +0 -34
- package/dist/modules/catalog/events.js.map +0 -7
- package/dist/modules/customers/events.js +0 -49
- package/dist/modules/customers/events.js.map +0 -7
- package/dist/modules/directory/events.js +0 -23
- package/dist/modules/directory/events.js.map +0 -7
- package/dist/modules/sales/events.js +0 -63
- package/dist/modules/sales/events.js.map +0 -7
- package/dist/modules/sales/lib/frontend/documentDataEvents.js +0 -25
- package/dist/modules/sales/lib/frontend/documentDataEvents.js.map +0 -7
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +0 -481
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/components/EventTriggersEditor.js +0 -553
- package/dist/modules/workflows/components/EventTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/events.js +0 -38
- package/dist/modules/workflows/events.js.map +0 -7
- package/dist/modules/workflows/examples/order-approval-definition.json +0 -257
- package/dist/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/dist/modules/workflows/lib/event-trigger-service.js +0 -308
- package/dist/modules/workflows/lib/event-trigger-service.js.map +0 -7
- package/dist/modules/workflows/migrations/Migration20260123143500.js +0 -36
- package/dist/modules/workflows/migrations/Migration20260123143500.js.map +0 -7
- package/dist/modules/workflows/subscribers/event-trigger.js +0 -78
- package/dist/modules/workflows/subscribers/event-trigger.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +0 -323
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js +0 -17
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js.map +0 -7
- package/dist/modules/workflows/widgets/injection-table.js +0 -19
- package/dist/modules/workflows/widgets/injection-table.js.map +0 -7
- package/generated/entities/workflow_event_trigger/index.ts +0 -15
- package/src/modules/auth/events.ts +0 -39
- package/src/modules/business_rules/api/execute/[ruleId]/route.ts +0 -163
- package/src/modules/catalog/events.ts +0 -45
- package/src/modules/customers/events.ts +0 -63
- package/src/modules/directory/events.ts +0 -31
- package/src/modules/sales/events.ts +0 -82
- package/src/modules/sales/lib/frontend/documentDataEvents.ts +0 -28
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +0 -581
- package/src/modules/workflows/components/EventTriggersEditor.tsx +0 -664
- package/src/modules/workflows/events.ts +0 -49
- package/src/modules/workflows/examples/order-approval-definition.json +0 -257
- package/src/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/src/modules/workflows/lib/event-trigger-service.ts +0 -557
- package/src/modules/workflows/migrations/Migration20260123143500.ts +0 -38
- package/src/modules/workflows/subscribers/event-trigger.ts +0 -109
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +0 -446
- package/src/modules/workflows/widgets/injection/order-approval/widget.ts +0 -16
- package/src/modules/workflows/widgets/injection-table.ts +0 -21
|
@@ -4,7 +4,7 @@ import { randomUUID } from 'crypto'
|
|
|
4
4
|
import { z } from 'zod'
|
|
5
5
|
import { registerCommand } from '@open-mercato/shared/lib/commands'
|
|
6
6
|
import type { CommandHandler } from '@open-mercato/shared/lib/commands'
|
|
7
|
-
import { emitCrudSideEffects, requireId
|
|
7
|
+
import { emitCrudSideEffects, requireId } from '@open-mercato/shared/lib/commands/helpers'
|
|
8
8
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
9
9
|
import type { EventBus } from '@open-mercato/events'
|
|
10
10
|
import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
|
|
@@ -89,29 +89,6 @@ import { resolveStatusEntryIdByValue } from '../lib/statusHelpers'
|
|
|
89
89
|
import { SalesDocumentNumberGenerator } from '../services/salesDocumentNumberGenerator'
|
|
90
90
|
import { loadSalesSettings } from './settings'
|
|
91
91
|
|
|
92
|
-
// CRUD events configuration for workflow triggers
|
|
93
|
-
const orderCrudEvents: CrudEventsConfig<SalesOrder> = {
|
|
94
|
-
module: 'sales',
|
|
95
|
-
entity: 'orders',
|
|
96
|
-
persistent: true,
|
|
97
|
-
buildPayload: (ctx) => ({
|
|
98
|
-
id: ctx.identifiers.id,
|
|
99
|
-
organizationId: ctx.identifiers.organizationId,
|
|
100
|
-
tenantId: ctx.identifiers.tenantId,
|
|
101
|
-
}),
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const quoteCrudEvents: CrudEventsConfig<SalesQuote> = {
|
|
105
|
-
module: 'sales',
|
|
106
|
-
entity: 'quotes',
|
|
107
|
-
persistent: true,
|
|
108
|
-
buildPayload: (ctx) => ({
|
|
109
|
-
id: ctx.identifiers.id,
|
|
110
|
-
organizationId: ctx.identifiers.organizationId,
|
|
111
|
-
tenantId: ctx.identifiers.tenantId,
|
|
112
|
-
}),
|
|
113
|
-
}
|
|
114
|
-
|
|
115
92
|
type DocumentAddressSnapshot = {
|
|
116
93
|
id: string
|
|
117
94
|
organizationId: string
|
|
@@ -3134,31 +3111,6 @@ const createQuoteCommand: CommandHandler<QuoteCreateInput, { quoteId: string }>
|
|
|
3134
3111
|
})
|
|
3135
3112
|
await em.flush()
|
|
3136
3113
|
|
|
3137
|
-
// Emit CRUD side effects to trigger workflow event listeners
|
|
3138
|
-
const dataEngine = ctx.container.resolve('dataEngine') as DataEngine
|
|
3139
|
-
await emitCrudSideEffects({
|
|
3140
|
-
dataEngine,
|
|
3141
|
-
action: 'created',
|
|
3142
|
-
entity: quote,
|
|
3143
|
-
identifiers: {
|
|
3144
|
-
id: quote.id,
|
|
3145
|
-
organizationId: quote.organizationId,
|
|
3146
|
-
tenantId: quote.tenantId,
|
|
3147
|
-
},
|
|
3148
|
-
events: quoteCrudEvents,
|
|
3149
|
-
indexer: { entityType: E.sales.sales_quote },
|
|
3150
|
-
})
|
|
3151
|
-
|
|
3152
|
-
// Invalidate cache
|
|
3153
|
-
const resourceKind = deriveResourceFromCommandId(createQuoteCommand.id) ?? 'sales.quote'
|
|
3154
|
-
await invalidateCrudCache(
|
|
3155
|
-
ctx.container,
|
|
3156
|
-
resourceKind,
|
|
3157
|
-
{ id: quote.id, organizationId: quote.organizationId, tenantId: quote.tenantId },
|
|
3158
|
-
ctx.auth?.tenantId ?? null,
|
|
3159
|
-
'created'
|
|
3160
|
-
)
|
|
3161
|
-
|
|
3162
3114
|
return { quoteId: quote.id }
|
|
3163
3115
|
},
|
|
3164
3116
|
captureAfter: async (_input, result, ctx) => {
|
|
@@ -3830,31 +3782,6 @@ const createOrderCommand: CommandHandler<OrderCreateInput, { orderId: string }>
|
|
|
3830
3782
|
})
|
|
3831
3783
|
await em.flush()
|
|
3832
3784
|
|
|
3833
|
-
// Emit CRUD side effects to trigger workflow event listeners
|
|
3834
|
-
const dataEngine = ctx.container.resolve('dataEngine') as DataEngine
|
|
3835
|
-
await emitCrudSideEffects({
|
|
3836
|
-
dataEngine,
|
|
3837
|
-
action: 'created',
|
|
3838
|
-
entity: order,
|
|
3839
|
-
identifiers: {
|
|
3840
|
-
id: order.id,
|
|
3841
|
-
organizationId: order.organizationId,
|
|
3842
|
-
tenantId: order.tenantId,
|
|
3843
|
-
},
|
|
3844
|
-
events: orderCrudEvents,
|
|
3845
|
-
indexer: { entityType: E.sales.sales_order },
|
|
3846
|
-
})
|
|
3847
|
-
|
|
3848
|
-
// Invalidate cache
|
|
3849
|
-
const resourceKind = deriveResourceFromCommandId(createOrderCommand.id) ?? 'sales.order'
|
|
3850
|
-
await invalidateCrudCache(
|
|
3851
|
-
ctx.container,
|
|
3852
|
-
resourceKind,
|
|
3853
|
-
{ id: order.id, organizationId: order.organizationId, tenantId: order.tenantId },
|
|
3854
|
-
ctx.auth?.tenantId ?? null,
|
|
3855
|
-
'created'
|
|
3856
|
-
)
|
|
3857
|
-
|
|
3858
3785
|
return { orderId: order.id }
|
|
3859
3786
|
},
|
|
3860
3787
|
captureAfter: async (_input, result, ctx) => {
|
|
@@ -125,9 +125,6 @@ type SeedScope = { tenantId: string; organizationId: string }
|
|
|
125
125
|
|
|
126
126
|
const ORDER_STATUS_DEFAULTS: SalesDictionarySeed[] = [
|
|
127
127
|
{ value: 'draft', label: 'Draft', color: '#94a3b8', icon: 'lucide:file-pen-line' },
|
|
128
|
-
{ value: 'pending_approval', label: 'Pending Approval', color: '#f59e0b', icon: 'lucide:hourglass' },
|
|
129
|
-
{ value: 'approved', label: 'Approved', color: '#16a34a', icon: 'lucide:check-circle' },
|
|
130
|
-
{ value: 'rejected', label: 'Rejected', color: '#ef4444', icon: 'lucide:x-circle' },
|
|
131
128
|
{ value: 'sent', label: 'Sent', color: '#0ea5e9', icon: 'lucide:send' },
|
|
132
129
|
{ value: 'confirmed', label: 'Confirmed', color: '#2563eb', icon: 'lucide:badge-check' },
|
|
133
130
|
{ value: 'in_fulfillment', label: 'In fulfillment', color: '#f59e0b', icon: 'lucide:loader-2' },
|
|
@@ -19,8 +19,6 @@ export const features = [
|
|
|
19
19
|
{ id: 'workflows.tasks.complete', title: 'Complete workflow tasks', module: moduleId },
|
|
20
20
|
{ id: 'workflows.signals.send', title: 'Send workflow signals', module: moduleId },
|
|
21
21
|
{ id: 'workflows.events.view', title: 'View workflow events', module: moduleId },
|
|
22
|
-
// Note: Event triggers are now embedded in workflow definitions.
|
|
23
|
-
// Trigger management permissions are covered by workflows.definitions.edit
|
|
24
22
|
]
|
|
25
23
|
|
|
26
24
|
export default features
|
|
@@ -194,14 +194,11 @@ describe('Workflow Instances API', () => {
|
|
|
194
194
|
const request = new NextRequest('http://localhost/api/workflows/instances?entityType=order&entityId=order-123')
|
|
195
195
|
await listInstances(request)
|
|
196
196
|
|
|
197
|
-
// The implementation uses JSONB $contains queries for metadata filtering
|
|
198
197
|
expect(mockEm.findAndCount).toHaveBeenCalledWith(
|
|
199
198
|
WorkflowInstance,
|
|
200
199
|
expect.objectContaining({
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
{ metadata: { $contains: { entityId: 'order-123' } } },
|
|
204
|
-
]),
|
|
200
|
+
'metadata.entityType': 'order',
|
|
201
|
+
'metadata.entityId': 'order-123',
|
|
205
202
|
}),
|
|
206
203
|
expect.any(Object)
|
|
207
204
|
)
|
|
@@ -70,33 +70,19 @@ export async function GET(request: NextRequest) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
if (status) {
|
|
73
|
-
|
|
74
|
-
const statuses = status.split(',').map(s => s.trim()).filter(Boolean)
|
|
75
|
-
if (statuses.length === 1) {
|
|
76
|
-
where.status = statuses[0]
|
|
77
|
-
} else if (statuses.length > 1) {
|
|
78
|
-
where.status = { $in: statuses }
|
|
79
|
-
}
|
|
73
|
+
where.status = status
|
|
80
74
|
}
|
|
81
75
|
|
|
82
76
|
if (correlationKey) {
|
|
83
77
|
where.correlationKey = correlationKey
|
|
84
78
|
}
|
|
85
79
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
metadata: { $contains: { entityType: entityType } }
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
if (entityId) {
|
|
96
|
-
where.$and.push({
|
|
97
|
-
metadata: { $contains: { entityId: entityId } }
|
|
98
|
-
})
|
|
99
|
-
}
|
|
80
|
+
if (entityType) {
|
|
81
|
+
where['metadata.entityType'] = entityType
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (entityId) {
|
|
85
|
+
where['metadata.entityId'] = entityId
|
|
100
86
|
}
|
|
101
87
|
|
|
102
88
|
const [instances, total] = await em.findAndCount(
|
|
@@ -67,13 +67,7 @@ export async function GET(request: NextRequest) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
if (status) {
|
|
70
|
-
|
|
71
|
-
const statusValues = status.split(',').map(s => s.trim()).filter(Boolean)
|
|
72
|
-
if (statusValues.length === 1) {
|
|
73
|
-
where.status = statusValues[0]
|
|
74
|
-
} else if (statusValues.length > 1) {
|
|
75
|
-
where.status = { $in: statusValues }
|
|
76
|
-
}
|
|
70
|
+
where.status = status
|
|
77
71
|
}
|
|
78
72
|
|
|
79
73
|
if (assignedTo) {
|
|
@@ -4,7 +4,7 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Edit Workflow Definition',
|
|
5
5
|
pageTitleKey: 'workflows.edit.title',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/workflows/definitions' },
|
|
8
8
|
{ label: 'Edit', labelKey: 'workflows.common.edit' },
|
|
9
9
|
],
|
|
10
10
|
}
|
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
} from '../../../components/formConfig'
|
|
20
20
|
import { StepsEditor } from '../../../components/StepsEditor'
|
|
21
21
|
import { TransitionsEditor } from '../../../components/TransitionsEditor'
|
|
22
|
-
import { EventTriggersEditor } from '../../../components/EventTriggersEditor'
|
|
23
22
|
|
|
24
23
|
export default function EditWorkflowDefinitionPage() {
|
|
25
24
|
const router = useRouter()
|
|
@@ -146,14 +145,6 @@ export default function EditWorkflowDefinitionPage() {
|
|
|
146
145
|
groups={formGroups}
|
|
147
146
|
submitLabel={t('workflows.form.update')}
|
|
148
147
|
/>
|
|
149
|
-
|
|
150
|
-
{/* Event Triggers Section */}
|
|
151
|
-
<div className="mt-8">
|
|
152
|
-
<EventTriggersEditor
|
|
153
|
-
workflowDefinitionId={definitionId!}
|
|
154
|
-
workflowId={definition?.workflowId}
|
|
155
|
-
/>
|
|
156
|
-
</div>
|
|
157
148
|
</PageBody>
|
|
158
149
|
</Page>
|
|
159
150
|
)
|
|
@@ -20,7 +20,7 @@ export const metadata = {
|
|
|
20
20
|
pageOrder: 100,
|
|
21
21
|
icon: createIcon,
|
|
22
22
|
breadcrumb: [
|
|
23
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
23
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/workflows/definitions' },
|
|
24
24
|
{ label: 'Create', labelKey: 'workflows.common.create' },
|
|
25
25
|
],
|
|
26
26
|
}
|
|
@@ -16,8 +16,6 @@ import {
|
|
|
16
16
|
} from '../../../components/formConfig'
|
|
17
17
|
import { StepsEditor } from '../../../components/StepsEditor'
|
|
18
18
|
import { TransitionsEditor } from '../../../components/TransitionsEditor'
|
|
19
|
-
import { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'
|
|
20
|
-
import { Zap } from 'lucide-react'
|
|
21
19
|
|
|
22
20
|
export default function CreateWorkflowDefinitionPage() {
|
|
23
21
|
const router = useRouter()
|
|
@@ -52,13 +50,6 @@ export default function CreateWorkflowDefinitionPage() {
|
|
|
52
50
|
return (
|
|
53
51
|
<Page>
|
|
54
52
|
<PageBody>
|
|
55
|
-
<Alert variant="info" className="mb-6">
|
|
56
|
-
<Zap className="w-4 h-4" />
|
|
57
|
-
<AlertTitle>Event Triggers</AlertTitle>
|
|
58
|
-
<AlertDescription>
|
|
59
|
-
After creating this workflow definition, you can configure event triggers to automatically start the workflow when specific events occur in the system.
|
|
60
|
-
</AlertDescription>
|
|
61
|
-
</Alert>
|
|
62
53
|
<CrudForm
|
|
63
54
|
title={t('workflows.create.title')}
|
|
64
55
|
backHref="/backend/definitions"
|
|
@@ -19,7 +19,7 @@ export const metadata = {
|
|
|
19
19
|
pageOrder: 150,
|
|
20
20
|
icon: visualEditorIcon,
|
|
21
21
|
breadcrumb: [
|
|
22
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
22
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/workflows/definitions' },
|
|
23
23
|
{ label: 'Visual Editor', labelKey: 'workflows.backend.definitions.visual_editor.title' },
|
|
24
24
|
],
|
|
25
25
|
}
|
|
@@ -34,8 +34,6 @@ import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
|
34
34
|
import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
35
35
|
import {CircleQuestionMark, Info, PanelTopClose, PanelTopOpen, Play, Save, Trash2} from 'lucide-react'
|
|
36
36
|
import { NODE_TYPE_ICONS, NODE_TYPE_COLORS, NODE_TYPE_LABELS } from '../../../lib/node-type-icons'
|
|
37
|
-
import { DefinitionTriggersEditor } from '../../../components/DefinitionTriggersEditor'
|
|
38
|
-
import type { WorkflowDefinitionTrigger } from '../../../data/entities'
|
|
39
37
|
import * as React from "react";
|
|
40
38
|
|
|
41
39
|
/**
|
|
@@ -78,7 +76,6 @@ export default function VisualEditorPage() {
|
|
|
78
76
|
const [icon, setIcon] = useState('')
|
|
79
77
|
const [effectiveFrom, setEffectiveFrom] = useState('')
|
|
80
78
|
const [effectiveTo, setEffectiveTo] = useState('')
|
|
81
|
-
const [triggers, setTriggers] = useState<WorkflowDefinitionTrigger[]>([])
|
|
82
79
|
|
|
83
80
|
// Load existing definition if ID is provided
|
|
84
81
|
useEffect(() => {
|
|
@@ -116,9 +113,6 @@ export default function VisualEditorPage() {
|
|
|
116
113
|
setNodes(graph.nodes)
|
|
117
114
|
setEdges(graph.edges)
|
|
118
115
|
|
|
119
|
-
// Load embedded triggers from definition
|
|
120
|
-
setTriggers(definition.definition?.triggers || [])
|
|
121
|
-
|
|
122
116
|
flash('Workflow loaded successfully', 'success')
|
|
123
117
|
} catch (error) {
|
|
124
118
|
console.error('Error loading workflow definition:', error)
|
|
@@ -290,12 +284,8 @@ export default function VisualEditorPage() {
|
|
|
290
284
|
return
|
|
291
285
|
}
|
|
292
286
|
|
|
293
|
-
// Generate definition data
|
|
294
|
-
const
|
|
295
|
-
const definitionData = {
|
|
296
|
-
...graphDefinition,
|
|
297
|
-
triggers: triggers.length > 0 ? triggers : undefined,
|
|
298
|
-
}
|
|
287
|
+
// Generate definition data
|
|
288
|
+
const definitionData = graphToDefinition(nodes, edges, { includePositions: true })
|
|
299
289
|
|
|
300
290
|
// Run Zod schema validation before saving
|
|
301
291
|
const schemaResult = workflowDefinitionDataSchema.safeParse(definitionData)
|
|
@@ -367,7 +357,7 @@ export default function VisualEditorPage() {
|
|
|
367
357
|
} finally {
|
|
368
358
|
setIsSaving(false)
|
|
369
359
|
}
|
|
370
|
-
}, [nodes, edges, workflowId, workflowName, description, version, enabled, category, tags,
|
|
360
|
+
}, [nodes, edges, workflowId, workflowName, description, version, enabled, category, tags, definitionId, router])
|
|
371
361
|
|
|
372
362
|
// Test workflow
|
|
373
363
|
const handleTest = useCallback(() => {
|
|
@@ -485,7 +475,6 @@ export default function VisualEditorPage() {
|
|
|
485
475
|
setIcon('')
|
|
486
476
|
setEffectiveFrom('')
|
|
487
477
|
setEffectiveTo('')
|
|
488
|
-
setTriggers([])
|
|
489
478
|
setShowClearConfirm(false)
|
|
490
479
|
flash('Canvas cleared', 'success')
|
|
491
480
|
}, [])
|
|
@@ -720,13 +709,6 @@ export default function VisualEditorPage() {
|
|
|
720
709
|
</div>
|
|
721
710
|
</div>
|
|
722
711
|
</div>
|
|
723
|
-
|
|
724
|
-
{/* Event Triggers - Always visible, managed as part of definition */}
|
|
725
|
-
<DefinitionTriggersEditor
|
|
726
|
-
value={triggers}
|
|
727
|
-
onChange={setTriggers}
|
|
728
|
-
className="mt-4"
|
|
729
|
-
/>
|
|
730
712
|
</div>
|
|
731
713
|
)}
|
|
732
714
|
|
|
@@ -4,8 +4,8 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Event Details',
|
|
5
5
|
pageTitleKey: 'workflows.events.detail.title',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
8
|
-
{ label: 'Events', labelKey: 'workflows.events.plural', href: '/backend/events' },
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/workflows/definitions' },
|
|
8
|
+
{ label: 'Events', labelKey: 'workflows.events.plural', href: '/backend/workflows/events' },
|
|
9
9
|
{ label: 'Details', labelKey: 'common.details' },
|
|
10
10
|
],
|
|
11
11
|
}
|
|
@@ -212,7 +212,7 @@ export default function WorkflowEventDetailPage() {
|
|
|
212
212
|
</dt>
|
|
213
213
|
<dd className="mt-1">
|
|
214
214
|
<Link
|
|
215
|
-
href={`/backend/instances/${event.workflowInstance.id}`}
|
|
215
|
+
href={`/backend/workflows/instances/${event.workflowInstance.id}`}
|
|
216
216
|
className="text-sm text-primary hover:underline font-mono"
|
|
217
217
|
>
|
|
218
218
|
{event.workflowInstance.id}
|
|
@@ -4,8 +4,8 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Workflow Instance Details',
|
|
5
5
|
pageTitleKey: 'workflows.instances.singular',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
8
|
-
{ label: 'Instances', labelKey: 'workflows.instances.plural', href: '/backend/instances' },
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/workflows/definitions' },
|
|
8
|
+
{ label: 'Instances', labelKey: 'workflows.instances.plural', href: '/backend/workflows/instances' },
|
|
9
9
|
{ label: 'Details', labelKey: 'common.details' },
|
|
10
10
|
],
|
|
11
11
|
}
|
|
@@ -4,8 +4,8 @@ export const metadata = {
|
|
|
4
4
|
pageTitle: 'Task Details',
|
|
5
5
|
pageTitleKey: 'workflows.tasks.singular',
|
|
6
6
|
breadcrumb: [
|
|
7
|
-
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/definitions' },
|
|
8
|
-
{ label: 'Tasks', labelKey: 'workflows.tasks.plural', href: '/backend/tasks' },
|
|
7
|
+
{ label: 'Workflows', labelKey: 'workflows.module.name', href: '/backend/workflows/definitions' },
|
|
8
|
+
{ label: 'Tasks', labelKey: 'workflows.tasks.plural', href: '/backend/workflows/tasks' },
|
|
9
9
|
{ label: 'Details', labelKey: 'common.details' },
|
|
10
10
|
],
|
|
11
11
|
}
|
|
@@ -72,6 +72,7 @@ export default function UserTasksListPage() {
|
|
|
72
72
|
params.set('offset', offset.toString())
|
|
73
73
|
|
|
74
74
|
if (filterValues.status) params.set('status', filterValues.status as string)
|
|
75
|
+
if (filterValues.myTasks === 'true') params.set('myTasks', 'true')
|
|
75
76
|
if (filterValues.overdue === 'true') params.set('overdue', 'true')
|
|
76
77
|
if (filterValues.workflowInstanceId) params.set('workflowInstanceId', filterValues.workflowInstanceId as string)
|
|
77
78
|
|
|
@@ -154,10 +155,10 @@ export default function UserTasksListPage() {
|
|
|
154
155
|
label: t('workflows.tasks.filters.status'),
|
|
155
156
|
options: [
|
|
156
157
|
{ label: t('common.all'), value: '' },
|
|
157
|
-
{ label: t('workflows.tasks.
|
|
158
|
-
{ label: t('workflows.tasks.
|
|
159
|
-
{ label: t('workflows.tasks.
|
|
160
|
-
{ label: t('workflows.tasks.
|
|
158
|
+
{ label: t('workflows.tasks.status.PENDING'), value: 'PENDING' },
|
|
159
|
+
{ label: t('workflows.tasks.status.IN_PROGRESS'), value: 'IN_PROGRESS' },
|
|
160
|
+
{ label: t('workflows.tasks.status.COMPLETED'), value: 'COMPLETED' },
|
|
161
|
+
{ label: t('workflows.tasks.status.CANCELLED'), value: 'CANCELLED' },
|
|
161
162
|
],
|
|
162
163
|
},
|
|
163
164
|
{
|
|
@@ -213,7 +214,7 @@ export default function UserTasksListPage() {
|
|
|
213
214
|
accessorKey: 'status',
|
|
214
215
|
cell: ({ row }) => (
|
|
215
216
|
<span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(row.original.status)}`}>
|
|
216
|
-
{t(`workflows.tasks.
|
|
217
|
+
{t(`workflows.tasks.status.${row.original.status}`)}
|
|
217
218
|
</span>
|
|
218
219
|
),
|
|
219
220
|
},
|
|
@@ -2,7 +2,6 @@ import type { ModuleCli } from '@open-mercato/shared/modules/registry'
|
|
|
2
2
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
3
3
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
4
4
|
import { WorkflowDefinition } from './data/entities'
|
|
5
|
-
import { BusinessRule, type RuleType } from '@open-mercato/core/modules/business_rules/data/entities'
|
|
6
5
|
import * as fs from 'fs'
|
|
7
6
|
import * as path from 'path'
|
|
8
7
|
import { fileURLToPath } from 'url'
|
|
@@ -284,111 +283,6 @@ const seedSimpleApproval: ModuleCli = {
|
|
|
284
283
|
},
|
|
285
284
|
}
|
|
286
285
|
|
|
287
|
-
/**
|
|
288
|
-
* Seed order approval example
|
|
289
|
-
*/
|
|
290
|
-
const seedOrderApproval: ModuleCli = {
|
|
291
|
-
command: 'seed-order-approval',
|
|
292
|
-
async run(rest: string[]) {
|
|
293
|
-
const args = parseArgs(rest)
|
|
294
|
-
const tenantId = String(args.tenantId ?? args.tenant ?? args.t ?? '')
|
|
295
|
-
const organizationId = String(args.organizationId ?? args.orgId ?? args.org ?? args.o ?? '')
|
|
296
|
-
|
|
297
|
-
if (!tenantId || !organizationId) {
|
|
298
|
-
console.error('Usage: mercato workflows seed-order-approval --tenant <tenantId> --org <organizationId>')
|
|
299
|
-
return
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
try {
|
|
303
|
-
const { resolve } = await createRequestContainer()
|
|
304
|
-
const em = resolve<EntityManager>('em')
|
|
305
|
-
|
|
306
|
-
// 1. Seed order approval guard rules first
|
|
307
|
-
const guardRulesPath = path.join(__dirname, 'examples', 'order-approval-guard-rules.json')
|
|
308
|
-
const guardRulesData = JSON.parse(fs.readFileSync(guardRulesPath, 'utf8')) as Array<{
|
|
309
|
-
ruleId: string
|
|
310
|
-
ruleName: string
|
|
311
|
-
ruleType: RuleType
|
|
312
|
-
entityType: string
|
|
313
|
-
description?: string
|
|
314
|
-
eventType?: string
|
|
315
|
-
conditionExpression?: Record<string, unknown>
|
|
316
|
-
enabled?: boolean
|
|
317
|
-
priority?: number
|
|
318
|
-
}>
|
|
319
|
-
|
|
320
|
-
let rulesSeeded = 0
|
|
321
|
-
let rulesSkipped = 0
|
|
322
|
-
for (const rule of guardRulesData) {
|
|
323
|
-
const existingRule = await em.findOne(BusinessRule, {
|
|
324
|
-
ruleId: rule.ruleId,
|
|
325
|
-
tenantId,
|
|
326
|
-
organizationId,
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
if (existingRule) {
|
|
330
|
-
rulesSkipped++
|
|
331
|
-
continue
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
const newRule = em.create(BusinessRule, {
|
|
335
|
-
...rule,
|
|
336
|
-
tenantId,
|
|
337
|
-
organizationId,
|
|
338
|
-
})
|
|
339
|
-
em.persist(newRule)
|
|
340
|
-
console.log(` ✓ Seeded guard rule: ${rule.ruleName}`)
|
|
341
|
-
rulesSeeded++
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (rulesSeeded > 0) {
|
|
345
|
-
await em.flush()
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// 2. Read the order approval workflow definition
|
|
349
|
-
const approvalPath = path.join(__dirname, 'examples', 'order-approval-definition.json')
|
|
350
|
-
const approvalData = JSON.parse(fs.readFileSync(approvalPath, 'utf8'))
|
|
351
|
-
|
|
352
|
-
// Check if it already exists
|
|
353
|
-
const existing = await em.findOne(WorkflowDefinition, {
|
|
354
|
-
workflowId: approvalData.workflowId,
|
|
355
|
-
tenantId,
|
|
356
|
-
organizationId,
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
if (existing) {
|
|
360
|
-
console.log(`✓ Order approval workflow '${approvalData.workflowId}' already exists (ID: ${existing.id})`)
|
|
361
|
-
console.log(` - Guard rules seeded: ${rulesSeeded}`)
|
|
362
|
-
console.log(` - Guard rules skipped: ${rulesSkipped}`)
|
|
363
|
-
return
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Create the workflow definition
|
|
367
|
-
const workflow = em.create(WorkflowDefinition, {
|
|
368
|
-
...approvalData,
|
|
369
|
-
tenantId,
|
|
370
|
-
organizationId,
|
|
371
|
-
})
|
|
372
|
-
|
|
373
|
-
await em.persistAndFlush(workflow)
|
|
374
|
-
|
|
375
|
-
console.log(`✓ Seeded order approval workflow: ${workflow.workflowName}`)
|
|
376
|
-
console.log(` - ID: ${workflow.id}`)
|
|
377
|
-
console.log(` - Workflow ID: ${workflow.workflowId}`)
|
|
378
|
-
console.log(` - Version: ${workflow.version}`)
|
|
379
|
-
console.log(` - Steps: ${workflow.definition.steps.length}`)
|
|
380
|
-
console.log(` - Transitions: ${workflow.definition.transitions.length}`)
|
|
381
|
-
console.log(` - Guard rules seeded: ${rulesSeeded}`)
|
|
382
|
-
console.log(` - Guard rules skipped: ${rulesSkipped}`)
|
|
383
|
-
console.log('')
|
|
384
|
-
console.log('Order approval workflow is ready!')
|
|
385
|
-
} catch (error) {
|
|
386
|
-
console.error('Error seeding order approval workflow:', error)
|
|
387
|
-
throw error
|
|
388
|
-
}
|
|
389
|
-
},
|
|
390
|
-
}
|
|
391
|
-
|
|
392
286
|
/**
|
|
393
287
|
* Start workflow activity worker
|
|
394
288
|
*/
|
|
@@ -472,10 +366,6 @@ const seedAll: ModuleCli = {
|
|
|
472
366
|
await seedSimpleApproval.run(rest)
|
|
473
367
|
console.log('')
|
|
474
368
|
|
|
475
|
-
// Seed order approval
|
|
476
|
-
await seedOrderApproval.run(rest)
|
|
477
|
-
console.log('')
|
|
478
|
-
|
|
479
369
|
console.log('✓ All example workflows seeded successfully!')
|
|
480
370
|
} catch (error) {
|
|
481
371
|
console.error('Error seeding workflows:', error)
|
|
@@ -554,7 +444,6 @@ const workflowsCliCommands = [
|
|
|
554
444
|
seedDemoWithRules,
|
|
555
445
|
seedSalesPipeline,
|
|
556
446
|
seedSimpleApproval,
|
|
557
|
-
seedOrderApproval,
|
|
558
447
|
seedAll,
|
|
559
448
|
]
|
|
560
449
|
|