@valentine-efagene/qshelter-common 2.0.74 → 2.0.76
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/client/browser.d.ts +5 -5
- package/dist/generated/client/client.d.ts +5 -5
- package/dist/generated/client/internal/class.d.ts +11 -11
- package/dist/generated/client/internal/class.js +2 -2
- package/dist/generated/client/internal/prismaNamespace.d.ts +95 -95
- package/dist/generated/client/internal/prismaNamespace.js +25 -25
- package/dist/generated/client/internal/prismaNamespaceBrowser.d.ts +27 -27
- package/dist/generated/client/internal/prismaNamespaceBrowser.js +25 -25
- package/dist/generated/client/models/Contract.d.ts +155 -155
- package/dist/generated/client/models/index.d.ts +3 -0
- package/dist/generated/client/models/index.js +3 -0
- package/dist/generated/client/models.d.ts +1 -1
- package/dist/src/events/bus/event-bus.service.d.ts +84 -0
- package/dist/src/events/bus/event-bus.service.js +372 -0
- package/dist/src/events/bus/event-bus.types.d.ts +73 -0
- package/dist/src/events/bus/event-bus.types.js +22 -0
- package/dist/src/events/index.d.ts +5 -6
- package/dist/src/events/index.js +7 -8
- package/dist/src/events/notifications/event-publisher.d.ts +41 -0
- package/dist/src/events/notifications/event-publisher.js +111 -0
- package/dist/src/events/notifications/notification-enums.d.ts +46 -0
- package/dist/src/events/notifications/notification-enums.js +59 -0
- package/dist/src/events/notifications/notification-event.d.ts +76 -0
- package/dist/src/events/notifications/notification-event.js +1 -0
- package/dist/src/events/unified/unified-event.service.d.ts +157 -0
- package/dist/src/events/unified/unified-event.service.js +177 -0
- package/dist/src/events/workflow/event-config.service.d.ts +123 -0
- package/dist/src/events/workflow/event-config.service.js +416 -0
- package/dist/src/events/workflow/event-seeder.d.ts +80 -0
- package/dist/src/events/workflow/event-seeder.js +343 -0
- package/dist/src/events/workflow/workflow-event.service.d.ts +230 -0
- package/dist/src/events/workflow/workflow-event.service.js +682 -0
- package/dist/src/events/workflow/workflow-types.d.ts +364 -0
- package/dist/src/events/workflow/workflow-types.js +22 -0
- package/package.json +4 -1
- package/prisma/schema.prisma +87 -79
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Type Seeder
|
|
3
|
+
*
|
|
4
|
+
* Utilities for seeding EventChannel, EventType, and EventHandler records.
|
|
5
|
+
* This allows admins to configure event-driven workflows programmatically.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { seedContractEventTypes } from '@valentine-efagene/qshelter-common';
|
|
10
|
+
*
|
|
11
|
+
* await seedContractEventTypes(prisma, tenantId);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Seed event channels
|
|
16
|
+
*/
|
|
17
|
+
export async function seedEventChannels(prisma, tenantId, channels) {
|
|
18
|
+
for (const channel of channels) {
|
|
19
|
+
await prisma.eventChannel.upsert({
|
|
20
|
+
where: {
|
|
21
|
+
tenantId_code: {
|
|
22
|
+
tenantId,
|
|
23
|
+
code: channel.code,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
create: {
|
|
27
|
+
tenantId,
|
|
28
|
+
code: channel.code,
|
|
29
|
+
name: channel.name,
|
|
30
|
+
description: channel.description,
|
|
31
|
+
enabled: channel.enabled ?? true,
|
|
32
|
+
},
|
|
33
|
+
update: {
|
|
34
|
+
name: channel.name,
|
|
35
|
+
description: channel.description,
|
|
36
|
+
enabled: channel.enabled ?? true,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Seed event types
|
|
43
|
+
*/
|
|
44
|
+
export async function seedEventTypes(prisma, tenantId, eventTypes) {
|
|
45
|
+
for (const eventType of eventTypes) {
|
|
46
|
+
// Get the channel
|
|
47
|
+
const channel = await prisma.eventChannel.findFirst({
|
|
48
|
+
where: {
|
|
49
|
+
tenantId,
|
|
50
|
+
code: eventType.channelCode,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
if (!channel) {
|
|
54
|
+
throw new Error(`Channel ${eventType.channelCode} not found for tenant ${tenantId}`);
|
|
55
|
+
}
|
|
56
|
+
await prisma.eventType.upsert({
|
|
57
|
+
where: {
|
|
58
|
+
tenantId_code: {
|
|
59
|
+
tenantId,
|
|
60
|
+
code: eventType.code,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
create: {
|
|
64
|
+
tenantId,
|
|
65
|
+
channelId: channel.id,
|
|
66
|
+
code: eventType.code,
|
|
67
|
+
name: eventType.name,
|
|
68
|
+
description: eventType.description,
|
|
69
|
+
payloadSchema: eventType.payloadSchema,
|
|
70
|
+
enabled: eventType.enabled ?? true,
|
|
71
|
+
},
|
|
72
|
+
update: {
|
|
73
|
+
channelId: channel.id,
|
|
74
|
+
name: eventType.name,
|
|
75
|
+
description: eventType.description,
|
|
76
|
+
payloadSchema: eventType.payloadSchema,
|
|
77
|
+
enabled: eventType.enabled ?? true,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Seed event handlers
|
|
84
|
+
*/
|
|
85
|
+
export async function seedEventHandlers(prisma, tenantId, handlers) {
|
|
86
|
+
for (const handler of handlers) {
|
|
87
|
+
// Get the event type
|
|
88
|
+
const eventType = await prisma.eventType.findFirst({
|
|
89
|
+
where: {
|
|
90
|
+
tenantId,
|
|
91
|
+
code: handler.eventTypeCode,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
if (!eventType) {
|
|
95
|
+
throw new Error(`Event type ${handler.eventTypeCode} not found for tenant ${tenantId}`);
|
|
96
|
+
}
|
|
97
|
+
// Check if handler already exists
|
|
98
|
+
const existing = await prisma.eventHandler.findFirst({
|
|
99
|
+
where: {
|
|
100
|
+
tenantId,
|
|
101
|
+
eventTypeId: eventType.id,
|
|
102
|
+
name: handler.name,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
if (existing) {
|
|
106
|
+
await prisma.eventHandler.update({
|
|
107
|
+
where: { id: existing.id },
|
|
108
|
+
data: {
|
|
109
|
+
description: handler.description,
|
|
110
|
+
handlerType: handler.handlerType,
|
|
111
|
+
config: handler.config,
|
|
112
|
+
priority: handler.priority ?? 100,
|
|
113
|
+
enabled: handler.enabled ?? true,
|
|
114
|
+
maxRetries: handler.maxRetries ?? 3,
|
|
115
|
+
retryDelayMs: handler.retryDelayMs ?? 1000,
|
|
116
|
+
filterCondition: handler.filterCondition,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
await prisma.eventHandler.create({
|
|
122
|
+
data: {
|
|
123
|
+
tenantId,
|
|
124
|
+
eventTypeId: eventType.id,
|
|
125
|
+
name: handler.name,
|
|
126
|
+
description: handler.description,
|
|
127
|
+
handlerType: handler.handlerType,
|
|
128
|
+
config: handler.config,
|
|
129
|
+
priority: handler.priority ?? 100,
|
|
130
|
+
enabled: handler.enabled ?? true,
|
|
131
|
+
maxRetries: handler.maxRetries ?? 3,
|
|
132
|
+
retryDelayMs: handler.retryDelayMs ?? 1000,
|
|
133
|
+
filterCondition: handler.filterCondition,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// Contract Event Types (Mortgage Service)
|
|
141
|
+
// ============================================================================
|
|
142
|
+
/**
|
|
143
|
+
* Contract event channels
|
|
144
|
+
*/
|
|
145
|
+
export const CONTRACT_CHANNELS = [
|
|
146
|
+
{
|
|
147
|
+
code: 'CONTRACTS',
|
|
148
|
+
name: 'Contract Events',
|
|
149
|
+
description: 'Events related to contract lifecycle (creation, activation, termination)',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
code: 'PAYMENTS',
|
|
153
|
+
name: 'Payment Events',
|
|
154
|
+
description: 'Events related to payments and installments',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
code: 'DOCUMENTS',
|
|
158
|
+
name: 'Document Events',
|
|
159
|
+
description: 'Events related to document upload, approval, and rejection',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
code: 'WORKFLOW',
|
|
163
|
+
name: 'Workflow Events',
|
|
164
|
+
description: 'Events related to workflow steps and phases',
|
|
165
|
+
},
|
|
166
|
+
];
|
|
167
|
+
/**
|
|
168
|
+
* Contract event types
|
|
169
|
+
*/
|
|
170
|
+
export const CONTRACT_EVENT_TYPES = [
|
|
171
|
+
// Contract lifecycle events
|
|
172
|
+
{
|
|
173
|
+
code: 'CONTRACT_CREATED',
|
|
174
|
+
name: 'Contract Created',
|
|
175
|
+
description: 'Fired when a new contract is created',
|
|
176
|
+
channelCode: 'CONTRACTS',
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
code: 'CONTRACT_ACTIVATED',
|
|
180
|
+
name: 'Contract Activated',
|
|
181
|
+
description: 'Fired when a contract is activated',
|
|
182
|
+
channelCode: 'CONTRACTS',
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
code: 'CONTRACT_TERMINATED',
|
|
186
|
+
name: 'Contract Terminated',
|
|
187
|
+
description: 'Fired when a contract is terminated',
|
|
188
|
+
channelCode: 'CONTRACTS',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
code: 'CONTRACT_TERMINATION_REQUESTED',
|
|
192
|
+
name: 'Contract Termination Requested',
|
|
193
|
+
description: 'Fired when a contract termination is requested',
|
|
194
|
+
channelCode: 'CONTRACTS',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
code: 'CONTRACT_TERMINATION_APPROVED',
|
|
198
|
+
name: 'Contract Termination Approved',
|
|
199
|
+
description: 'Fired when a contract termination is approved',
|
|
200
|
+
channelCode: 'CONTRACTS',
|
|
201
|
+
},
|
|
202
|
+
// Payment events
|
|
203
|
+
{
|
|
204
|
+
code: 'PAYMENT_RECEIVED',
|
|
205
|
+
name: 'Payment Received',
|
|
206
|
+
description: 'Fired when a payment is successfully received',
|
|
207
|
+
channelCode: 'PAYMENTS',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
code: 'PAYMENT_FAILED',
|
|
211
|
+
name: 'Payment Failed',
|
|
212
|
+
description: 'Fired when a payment fails',
|
|
213
|
+
channelCode: 'PAYMENTS',
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
code: 'PAYMENT_DUE_REMINDER',
|
|
217
|
+
name: 'Payment Due Reminder',
|
|
218
|
+
description: 'Fired to remind buyer of upcoming payment',
|
|
219
|
+
channelCode: 'PAYMENTS',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
code: 'PAYMENT_OVERDUE',
|
|
223
|
+
name: 'Payment Overdue',
|
|
224
|
+
description: 'Fired when a payment is overdue',
|
|
225
|
+
channelCode: 'PAYMENTS',
|
|
226
|
+
},
|
|
227
|
+
// Document events
|
|
228
|
+
{
|
|
229
|
+
code: 'DOCUMENT_UPLOADED',
|
|
230
|
+
name: 'Document Uploaded',
|
|
231
|
+
description: 'Fired when a document is uploaded',
|
|
232
|
+
channelCode: 'DOCUMENTS',
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
code: 'DOCUMENT_APPROVED',
|
|
236
|
+
name: 'Document Approved',
|
|
237
|
+
description: 'Fired when a document is approved',
|
|
238
|
+
channelCode: 'DOCUMENTS',
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
code: 'DOCUMENT_REJECTED',
|
|
242
|
+
name: 'Document Rejected',
|
|
243
|
+
description: 'Fired when a document is rejected',
|
|
244
|
+
channelCode: 'DOCUMENTS',
|
|
245
|
+
},
|
|
246
|
+
// Workflow events
|
|
247
|
+
{
|
|
248
|
+
code: 'PHASE_ACTIVATED',
|
|
249
|
+
name: 'Phase Activated',
|
|
250
|
+
description: 'Fired when a contract phase is activated',
|
|
251
|
+
channelCode: 'WORKFLOW',
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
code: 'PHASE_COMPLETED',
|
|
255
|
+
name: 'Phase Completed',
|
|
256
|
+
description: 'Fired when a contract phase is completed',
|
|
257
|
+
channelCode: 'WORKFLOW',
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
code: 'STEP_COMPLETED',
|
|
261
|
+
name: 'Step Completed',
|
|
262
|
+
description: 'Fired when a workflow step is completed',
|
|
263
|
+
channelCode: 'WORKFLOW',
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
code: 'STEP_REJECTED',
|
|
267
|
+
name: 'Step Rejected',
|
|
268
|
+
description: 'Fired when a workflow step is rejected',
|
|
269
|
+
channelCode: 'WORKFLOW',
|
|
270
|
+
},
|
|
271
|
+
];
|
|
272
|
+
/**
|
|
273
|
+
* Seed all contract event types
|
|
274
|
+
*/
|
|
275
|
+
export async function seedContractEventTypes(prisma, tenantId) {
|
|
276
|
+
console.log(`Seeding contract event types for tenant ${tenantId}...`);
|
|
277
|
+
// Seed channels
|
|
278
|
+
await seedEventChannels(prisma, tenantId, CONTRACT_CHANNELS);
|
|
279
|
+
console.log(`✓ Seeded ${CONTRACT_CHANNELS.length} event channels`);
|
|
280
|
+
// Seed event types
|
|
281
|
+
await seedEventTypes(prisma, tenantId, CONTRACT_EVENT_TYPES);
|
|
282
|
+
console.log(`✓ Seeded ${CONTRACT_EVENT_TYPES.length} event types`);
|
|
283
|
+
console.log('✓ Contract event types seeded successfully');
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Seed example email notification handlers
|
|
287
|
+
*
|
|
288
|
+
* Note: In production, admins would configure these via the UI.
|
|
289
|
+
* This is just an example for testing.
|
|
290
|
+
*/
|
|
291
|
+
export async function seedExampleEmailHandlers(prisma, tenantId) {
|
|
292
|
+
const handlers = [
|
|
293
|
+
{
|
|
294
|
+
eventTypeCode: 'CONTRACT_CREATED',
|
|
295
|
+
name: 'Send Contract Created Email',
|
|
296
|
+
description: 'Send email notification when contract is created',
|
|
297
|
+
handlerType: 'SEND_EMAIL',
|
|
298
|
+
config: {
|
|
299
|
+
notificationType: 'CONTRACT_CREATED',
|
|
300
|
+
recipientPath: '$.buyerEmail',
|
|
301
|
+
templateData: {
|
|
302
|
+
contractNumber: '$.contractNumber',
|
|
303
|
+
propertyName: '$.propertyName',
|
|
304
|
+
totalAmount: '$.totalAmount',
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
priority: 100,
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
eventTypeCode: 'PAYMENT_RECEIVED',
|
|
311
|
+
name: 'Send Payment Received Email',
|
|
312
|
+
description: 'Send email notification when payment is received',
|
|
313
|
+
handlerType: 'SEND_EMAIL',
|
|
314
|
+
config: {
|
|
315
|
+
notificationType: 'PAYMENT_RECEIVED',
|
|
316
|
+
recipientPath: '$.buyerEmail',
|
|
317
|
+
templateData: {
|
|
318
|
+
contractNumber: '$.contractNumber',
|
|
319
|
+
paymentAmount: '$.amount',
|
|
320
|
+
paymentReference: '$.reference',
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
priority: 100,
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
eventTypeCode: 'DOCUMENT_APPROVED',
|
|
327
|
+
name: 'Send Document Approved Email',
|
|
328
|
+
description: 'Send email notification when document is approved',
|
|
329
|
+
handlerType: 'SEND_EMAIL',
|
|
330
|
+
config: {
|
|
331
|
+
notificationType: 'DOCUMENT_APPROVED',
|
|
332
|
+
recipientPath: '$.buyerEmail',
|
|
333
|
+
templateData: {
|
|
334
|
+
documentType: '$.documentType',
|
|
335
|
+
stepName: '$.stepName',
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
priority: 100,
|
|
339
|
+
},
|
|
340
|
+
];
|
|
341
|
+
await seedEventHandlers(prisma, tenantId, handlers);
|
|
342
|
+
console.log(`✓ Seeded ${handlers.length} example email handlers`);
|
|
343
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Event Service
|
|
3
|
+
*
|
|
4
|
+
* Handles emission and processing of workflow events.
|
|
5
|
+
* Events are stored in the database and processed by registered handlers.
|
|
6
|
+
*
|
|
7
|
+
* Design principles:
|
|
8
|
+
* 1. Events are immutable once emitted
|
|
9
|
+
* 2. Handlers are configured by admins, not hardcoded
|
|
10
|
+
* 3. Each handler execution is logged for audit
|
|
11
|
+
* 4. Failed handlers can be retried
|
|
12
|
+
* 5. Events can be correlated for tracing
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const eventService = new WorkflowEventService(prisma);
|
|
17
|
+
*
|
|
18
|
+
* // Emit an event
|
|
19
|
+
* const event = await eventService.emit(tenantId, {
|
|
20
|
+
* eventType: 'DOCUMENT_UPLOADED',
|
|
21
|
+
* payload: {
|
|
22
|
+
* contractId: 'ctr_123',
|
|
23
|
+
* stepId: 'step_456',
|
|
24
|
+
* documentUrl: 'https://...',
|
|
25
|
+
* },
|
|
26
|
+
* source: 'contract-service',
|
|
27
|
+
* actor: { id: 'user_789', type: 'USER' },
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Process the event (run all handlers)
|
|
31
|
+
* const result = await eventService.processEvent(event.id);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
import { PrismaClient } from '../../../generated/client/client';
|
|
35
|
+
import type { EmitEventInput, WorkflowEventData, ProcessEventResult } from './workflow-types';
|
|
36
|
+
import { EventPublisher } from '../notifications/event-publisher';
|
|
37
|
+
/**
|
|
38
|
+
* Automation registry interface for RUN_AUTOMATION handlers
|
|
39
|
+
*/
|
|
40
|
+
export interface AutomationRegistry {
|
|
41
|
+
get(automationName: string): ((inputs: Record<string, unknown>, tenantId: string) => Promise<unknown>) | undefined;
|
|
42
|
+
register(automationName: string, handler: (inputs: Record<string, unknown>, tenantId: string) => Promise<unknown>): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Service registry interface for internal handlers (legacy support)
|
|
46
|
+
*/
|
|
47
|
+
export interface ServiceRegistry {
|
|
48
|
+
get(serviceName: string): any | undefined;
|
|
49
|
+
register(serviceName: string, service: any): void;
|
|
50
|
+
}
|
|
51
|
+
export declare class WorkflowEventService {
|
|
52
|
+
private prisma;
|
|
53
|
+
private automationRegistry;
|
|
54
|
+
private eventPublisher;
|
|
55
|
+
constructor(prisma: PrismaClient, automationRegistry?: AutomationRegistry, eventPublisher?: EventPublisher);
|
|
56
|
+
/**
|
|
57
|
+
* Register an automation for RUN_AUTOMATION handlers
|
|
58
|
+
*
|
|
59
|
+
* Automations are business logic functions that can be triggered by events.
|
|
60
|
+
* Example: "calculateLateFee", "sendWelcomePackage", "archiveContract"
|
|
61
|
+
*/
|
|
62
|
+
registerAutomation(name: string, handler: (inputs: Record<string, unknown>, tenantId: string) => Promise<unknown>): void;
|
|
63
|
+
/**
|
|
64
|
+
* Emit an event
|
|
65
|
+
*
|
|
66
|
+
* This creates an event record and optionally processes it immediately
|
|
67
|
+
* or leaves it for async processing by a worker.
|
|
68
|
+
*
|
|
69
|
+
* @param tenantId - Tenant context
|
|
70
|
+
* @param input - Event details
|
|
71
|
+
* @param processImmediately - Whether to process handlers now (default: false)
|
|
72
|
+
*/
|
|
73
|
+
emit(tenantId: string, input: EmitEventInput, processImmediately?: boolean): Promise<WorkflowEventData>;
|
|
74
|
+
/**
|
|
75
|
+
* Process an event by executing all registered handlers
|
|
76
|
+
*
|
|
77
|
+
* This is typically called by a worker/queue processor,
|
|
78
|
+
* but can also be called synchronously for simple cases.
|
|
79
|
+
*/
|
|
80
|
+
processEvent(eventId: string): Promise<ProcessEventResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Get pending events for processing (for worker/queue)
|
|
83
|
+
*/
|
|
84
|
+
getPendingEvents(tenantId?: string, limit?: number): Promise<WorkflowEventData[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Get events by correlation ID (for tracing related events)
|
|
87
|
+
*/
|
|
88
|
+
getEventsByCorrelation(tenantId: string, correlationId: string): Promise<WorkflowEventData[]>;
|
|
89
|
+
/**
|
|
90
|
+
* Get event with executions (for debugging/auditing)
|
|
91
|
+
*/
|
|
92
|
+
getEventWithExecutions(tenantId: string, eventId: string): Promise<({
|
|
93
|
+
eventType: {
|
|
94
|
+
channel: {
|
|
95
|
+
name: string;
|
|
96
|
+
id: string;
|
|
97
|
+
tenantId: string;
|
|
98
|
+
createdAt: Date;
|
|
99
|
+
updatedAt: Date;
|
|
100
|
+
description: string | null;
|
|
101
|
+
enabled: boolean;
|
|
102
|
+
code: string;
|
|
103
|
+
};
|
|
104
|
+
} & {
|
|
105
|
+
name: string;
|
|
106
|
+
id: string;
|
|
107
|
+
tenantId: string;
|
|
108
|
+
createdAt: Date;
|
|
109
|
+
updatedAt: Date;
|
|
110
|
+
description: string | null;
|
|
111
|
+
enabled: boolean;
|
|
112
|
+
code: string;
|
|
113
|
+
channelId: string;
|
|
114
|
+
payloadSchema: import("@prisma/client/runtime/client").JsonValue | null;
|
|
115
|
+
};
|
|
116
|
+
executions: ({
|
|
117
|
+
handler: {
|
|
118
|
+
name: string;
|
|
119
|
+
id: string;
|
|
120
|
+
handlerType: import("./workflow-types").EventHandlerType;
|
|
121
|
+
};
|
|
122
|
+
} & {
|
|
123
|
+
id: string;
|
|
124
|
+
createdAt: Date;
|
|
125
|
+
status: import("./workflow-types").ExecutionStatus;
|
|
126
|
+
handlerId: string;
|
|
127
|
+
completedAt: Date | null;
|
|
128
|
+
error: string | null;
|
|
129
|
+
eventId: string;
|
|
130
|
+
attempt: number;
|
|
131
|
+
input: import("@prisma/client/runtime/client").JsonValue | null;
|
|
132
|
+
output: import("@prisma/client/runtime/client").JsonValue | null;
|
|
133
|
+
errorCode: string | null;
|
|
134
|
+
startedAt: Date | null;
|
|
135
|
+
durationMs: number | null;
|
|
136
|
+
})[];
|
|
137
|
+
} & {
|
|
138
|
+
id: string;
|
|
139
|
+
tenantId: string;
|
|
140
|
+
createdAt: Date;
|
|
141
|
+
status: import("./workflow-types").WorkflowEventStatus;
|
|
142
|
+
processedAt: Date | null;
|
|
143
|
+
actorId: string | null;
|
|
144
|
+
actorType: import("./workflow-types").ActorType;
|
|
145
|
+
eventTypeId: string;
|
|
146
|
+
payload: import("@prisma/client/runtime/client").JsonValue;
|
|
147
|
+
correlationId: string | null;
|
|
148
|
+
causationId: string | null;
|
|
149
|
+
source: string;
|
|
150
|
+
error: string | null;
|
|
151
|
+
}) | null>;
|
|
152
|
+
/**
|
|
153
|
+
* Execute a handler based on its type
|
|
154
|
+
*
|
|
155
|
+
* Handler types are business-friendly names that abstract the underlying implementation:
|
|
156
|
+
* - SEND_EMAIL: Send email via notification service (SNS → SQS → SES)
|
|
157
|
+
* - SEND_SMS: Send SMS via notification service
|
|
158
|
+
* - SEND_PUSH: Send push notification via notification service
|
|
159
|
+
* - CALL_WEBHOOK: Make HTTP request to external URL
|
|
160
|
+
* - ADVANCE_WORKFLOW: Move workflow steps forward/backward
|
|
161
|
+
* - RUN_AUTOMATION: Execute registered business logic automation
|
|
162
|
+
*/
|
|
163
|
+
private executeHandler;
|
|
164
|
+
/**
|
|
165
|
+
* Execute SEND_EMAIL handler
|
|
166
|
+
*
|
|
167
|
+
* Sends an email via the notification service using SNS → SQS → SES.
|
|
168
|
+
* Business users configure: template, recipient, and template data.
|
|
169
|
+
*/
|
|
170
|
+
private executeSendEmailHandler;
|
|
171
|
+
/**
|
|
172
|
+
* Execute SEND_SMS handler
|
|
173
|
+
*
|
|
174
|
+
* Sends an SMS via the notification service.
|
|
175
|
+
* Business users configure: template, recipient phone, and template data.
|
|
176
|
+
*/
|
|
177
|
+
private executeSendSmsHandler;
|
|
178
|
+
/**
|
|
179
|
+
* Execute SEND_PUSH handler
|
|
180
|
+
*
|
|
181
|
+
* Sends a push notification via the notification service.
|
|
182
|
+
* Business users configure: template, recipient user, and template data.
|
|
183
|
+
*/
|
|
184
|
+
private executeSendPushHandler;
|
|
185
|
+
/**
|
|
186
|
+
* Build notification payload from config and event payload
|
|
187
|
+
*/
|
|
188
|
+
private buildNotificationPayload;
|
|
189
|
+
/**
|
|
190
|
+
* Execute CALL_WEBHOOK handler
|
|
191
|
+
*
|
|
192
|
+
* Makes an HTTP request to an external URL.
|
|
193
|
+
* Business users configure: URL, method, headers, and body mapping.
|
|
194
|
+
*/
|
|
195
|
+
private executeCallWebhookHandler;
|
|
196
|
+
/**
|
|
197
|
+
* Execute ADVANCE_WORKFLOW handler
|
|
198
|
+
*
|
|
199
|
+
* Advances or modifies workflow state.
|
|
200
|
+
* Business users configure: action (approve/reject/skip), step path, and data.
|
|
201
|
+
*/
|
|
202
|
+
private executeAdvanceWorkflowHandler;
|
|
203
|
+
/**
|
|
204
|
+
* Execute RUN_AUTOMATION handler
|
|
205
|
+
*
|
|
206
|
+
* Runs a registered business logic automation.
|
|
207
|
+
* Business users select from pre-defined automations like
|
|
208
|
+
* "Calculate Mortgage Payment", "Generate Contract", etc.
|
|
209
|
+
*/
|
|
210
|
+
private executeRunAutomationHandler;
|
|
211
|
+
/**
|
|
212
|
+
* Evaluate a filter condition against the payload
|
|
213
|
+
*/
|
|
214
|
+
private evaluateFilterCondition;
|
|
215
|
+
/**
|
|
216
|
+
* Transform payload using a mapping
|
|
217
|
+
*/
|
|
218
|
+
private transformPayload;
|
|
219
|
+
/**
|
|
220
|
+
* Resolve a dot-notation path in an object
|
|
221
|
+
*/
|
|
222
|
+
private resolvePath;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Create a workflow event service instance
|
|
226
|
+
*
|
|
227
|
+
* @param prisma - Prisma client for database access
|
|
228
|
+
* @param automationRegistry - Optional registry of business automations
|
|
229
|
+
*/
|
|
230
|
+
export declare function createWorkflowEventService(prisma: PrismaClient, automationRegistry?: AutomationRegistry): WorkflowEventService;
|