@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,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-Driven Workflow Types
|
|
3
|
+
*
|
|
4
|
+
* These types define the structure for a configurable event system
|
|
5
|
+
* where admins can define event types, channels, and handlers.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* 1. EventChannel - Logical grouping of events (e.g., "CONTRACTS", "PAYMENTS")
|
|
9
|
+
* 2. EventType - Specific event types (e.g., "DOCUMENT_UPLOADED", "STEP_COMPLETED")
|
|
10
|
+
* 3. EventHandler - What to do when an event fires (send email, call webhook, etc.)
|
|
11
|
+
* 4. WorkflowEvent - Actual event instances (audit log)
|
|
12
|
+
* 5. EventHandlerExecution - Log of handler executions
|
|
13
|
+
*
|
|
14
|
+
* Handler types are business-friendly so non-technical admins can configure them:
|
|
15
|
+
* - SEND_EMAIL: Send an email to someone
|
|
16
|
+
* - SEND_SMS: Send a text message
|
|
17
|
+
* - SEND_PUSH: Send a push notification
|
|
18
|
+
* - CALL_WEBHOOK: Call an external API
|
|
19
|
+
* - ADVANCE_WORKFLOW: Move workflow forward
|
|
20
|
+
* - RUN_AUTOMATION: Execute business logic
|
|
21
|
+
*/
|
|
22
|
+
export type { EventHandlerType, ActorType, WorkflowEventStatus, ExecutionStatus, } from '../../../generated/client/enums';
|
|
23
|
+
/**
|
|
24
|
+
* Configuration for SEND_EMAIL handler type
|
|
25
|
+
* Sends an email notification to specified recipients
|
|
26
|
+
*/
|
|
27
|
+
export interface SendEmailHandlerConfig {
|
|
28
|
+
type: 'SEND_EMAIL';
|
|
29
|
+
/** Email template name (e.g., "documentApproved", "paymentReminder") */
|
|
30
|
+
template: string;
|
|
31
|
+
/**
|
|
32
|
+
* Notification type for the notification service.
|
|
33
|
+
* This maps to templates in the notification service.
|
|
34
|
+
*/
|
|
35
|
+
notificationType: string;
|
|
36
|
+
/**
|
|
37
|
+
* Who to send the email to. Use JSONPath to extract from event payload.
|
|
38
|
+
* Examples: "$.buyer.email", "$.user.email"
|
|
39
|
+
*/
|
|
40
|
+
recipientPath: string;
|
|
41
|
+
/**
|
|
42
|
+
* Map event payload fields to template variables
|
|
43
|
+
* Example: { "userName": "$.buyer.firstName", "amount": "$.payment.amount" }
|
|
44
|
+
*/
|
|
45
|
+
templateData?: Record<string, string>;
|
|
46
|
+
/** Static data to always include in template */
|
|
47
|
+
staticData?: Record<string, unknown>;
|
|
48
|
+
/** Priority level */
|
|
49
|
+
priority?: 'low' | 'normal' | 'high' | 'urgent';
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Configuration for SEND_SMS handler type
|
|
53
|
+
* Sends an SMS text message
|
|
54
|
+
*/
|
|
55
|
+
export interface SendSmsHandlerConfig {
|
|
56
|
+
type: 'SEND_SMS';
|
|
57
|
+
/** SMS template name */
|
|
58
|
+
template: string;
|
|
59
|
+
/**
|
|
60
|
+
* Notification type for the notification service.
|
|
61
|
+
*/
|
|
62
|
+
notificationType: string;
|
|
63
|
+
/**
|
|
64
|
+
* Phone number path in event payload
|
|
65
|
+
* Example: "$.buyer.phone"
|
|
66
|
+
*/
|
|
67
|
+
recipientPath: string;
|
|
68
|
+
/** Map event payload fields to template variables */
|
|
69
|
+
templateData?: Record<string, string>;
|
|
70
|
+
/** Static data to always include in template */
|
|
71
|
+
staticData?: Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Configuration for SEND_PUSH handler type
|
|
75
|
+
* Sends a push notification to user's device
|
|
76
|
+
*/
|
|
77
|
+
export interface SendPushHandlerConfig {
|
|
78
|
+
type: 'SEND_PUSH';
|
|
79
|
+
/** Push notification title */
|
|
80
|
+
title: string;
|
|
81
|
+
/** Push notification body (can use {{variables}}) */
|
|
82
|
+
body: string;
|
|
83
|
+
/**
|
|
84
|
+
* Notification type for the notification service.
|
|
85
|
+
*/
|
|
86
|
+
notificationType: string;
|
|
87
|
+
/**
|
|
88
|
+
* User ID path in event payload (to find their device)
|
|
89
|
+
* Example: "$.buyer.id"
|
|
90
|
+
*/
|
|
91
|
+
recipientPath: string;
|
|
92
|
+
/** Deep link to open in app */
|
|
93
|
+
deepLink?: string;
|
|
94
|
+
/** Map event payload fields to notification variables */
|
|
95
|
+
templateData?: Record<string, string>;
|
|
96
|
+
/** Static data to always include in notification */
|
|
97
|
+
staticData?: Record<string, unknown>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Configuration for CALL_WEBHOOK handler type
|
|
101
|
+
* Calls an external API endpoint
|
|
102
|
+
*/
|
|
103
|
+
export interface CallWebhookHandlerConfig {
|
|
104
|
+
type: 'CALL_WEBHOOK';
|
|
105
|
+
/** The URL to call */
|
|
106
|
+
url: string;
|
|
107
|
+
/** HTTP method */
|
|
108
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
109
|
+
/** Optional headers to include */
|
|
110
|
+
headers?: Record<string, string>;
|
|
111
|
+
/**
|
|
112
|
+
* Map event payload fields to request body
|
|
113
|
+
* Example: { "orderId": "$.contract.id", "status": "$.status" }
|
|
114
|
+
*/
|
|
115
|
+
bodyMapping?: Record<string, string>;
|
|
116
|
+
/** Timeout in milliseconds (default: 30000) */
|
|
117
|
+
timeoutMs?: number;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Configuration for ADVANCE_WORKFLOW handler type
|
|
121
|
+
* Advances or modifies a workflow step
|
|
122
|
+
*/
|
|
123
|
+
export interface AdvanceWorkflowHandlerConfig {
|
|
124
|
+
type: 'ADVANCE_WORKFLOW';
|
|
125
|
+
/** What action to take */
|
|
126
|
+
action: 'complete_step' | 'skip_step' | 'fail_step' | 'activate_phase';
|
|
127
|
+
/**
|
|
128
|
+
* Step ID path in event payload (if action targets a specific step)
|
|
129
|
+
* Example: "$.stepId"
|
|
130
|
+
*/
|
|
131
|
+
stepIdPath?: string;
|
|
132
|
+
/**
|
|
133
|
+
* Phase ID path in event payload (if action targets a phase)
|
|
134
|
+
* Example: "$.phaseId"
|
|
135
|
+
*/
|
|
136
|
+
phaseIdPath?: string;
|
|
137
|
+
/** Static step ID (if not using path) */
|
|
138
|
+
stepId?: string;
|
|
139
|
+
/** Static workflow ID */
|
|
140
|
+
workflowId?: string;
|
|
141
|
+
/** Static phase ID */
|
|
142
|
+
phaseId?: string;
|
|
143
|
+
/** Additional data to pass to the action */
|
|
144
|
+
data?: Record<string, unknown>;
|
|
145
|
+
/** Reason to record for the action */
|
|
146
|
+
reason?: string;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Configuration for RUN_AUTOMATION handler type
|
|
150
|
+
* Executes internal business logic
|
|
151
|
+
*/
|
|
152
|
+
export interface RunAutomationHandlerConfig {
|
|
153
|
+
type: 'RUN_AUTOMATION';
|
|
154
|
+
/** The automation to run (registered automation name) */
|
|
155
|
+
automation: string;
|
|
156
|
+
/**
|
|
157
|
+
* Map event payload fields to automation inputs
|
|
158
|
+
* Example: { "contractId": "$.contract.id", "amount": "$.payment.amount" }
|
|
159
|
+
*/
|
|
160
|
+
inputMapping?: Record<string, string>;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Union type for all handler configurations
|
|
164
|
+
*/
|
|
165
|
+
export type HandlerConfig = SendEmailHandlerConfig | SendSmsHandlerConfig | SendPushHandlerConfig | CallWebhookHandlerConfig | AdvanceWorkflowHandlerConfig | RunAutomationHandlerConfig;
|
|
166
|
+
/**
|
|
167
|
+
* Input for emitting an event
|
|
168
|
+
*/
|
|
169
|
+
export interface EmitEventInput {
|
|
170
|
+
/** Event type code (e.g., "DOCUMENT_UPLOADED") */
|
|
171
|
+
eventType: string;
|
|
172
|
+
/** Event payload */
|
|
173
|
+
payload: Record<string, unknown>;
|
|
174
|
+
/** Source of the event (service name) */
|
|
175
|
+
source: string;
|
|
176
|
+
/** Actor information */
|
|
177
|
+
actor?: {
|
|
178
|
+
id: string;
|
|
179
|
+
type: 'USER' | 'API_KEY' | 'SYSTEM' | 'WEBHOOK';
|
|
180
|
+
};
|
|
181
|
+
/** Correlation ID for tracing related events */
|
|
182
|
+
correlationId?: string;
|
|
183
|
+
/** Causation ID (which event caused this one) */
|
|
184
|
+
causationId?: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Event with full metadata (returned from queries)
|
|
188
|
+
*/
|
|
189
|
+
export interface WorkflowEventData {
|
|
190
|
+
id: string;
|
|
191
|
+
tenantId: string;
|
|
192
|
+
eventTypeId: string;
|
|
193
|
+
eventTypeCode: string;
|
|
194
|
+
channelCode: string;
|
|
195
|
+
payload: Record<string, unknown>;
|
|
196
|
+
source: string;
|
|
197
|
+
actorId: string | null;
|
|
198
|
+
actorType: 'USER' | 'API_KEY' | 'SYSTEM' | 'WEBHOOK';
|
|
199
|
+
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'SKIPPED';
|
|
200
|
+
correlationId: string | null;
|
|
201
|
+
causationId: string | null;
|
|
202
|
+
error: string | null;
|
|
203
|
+
processedAt: Date | null;
|
|
204
|
+
createdAt: Date;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Result of processing an event
|
|
208
|
+
*/
|
|
209
|
+
export interface ProcessEventResult {
|
|
210
|
+
eventId: string;
|
|
211
|
+
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'SKIPPED';
|
|
212
|
+
handlersExecuted: number;
|
|
213
|
+
handlersSucceeded: number;
|
|
214
|
+
handlersFailed: number;
|
|
215
|
+
errors: Array<{
|
|
216
|
+
handlerId: string;
|
|
217
|
+
handlerName: string;
|
|
218
|
+
error: string;
|
|
219
|
+
}>;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Input for creating an event channel
|
|
223
|
+
*/
|
|
224
|
+
export interface CreateEventChannelInput {
|
|
225
|
+
code: string;
|
|
226
|
+
name: string;
|
|
227
|
+
description?: string;
|
|
228
|
+
enabled?: boolean;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Input for updating an event channel
|
|
232
|
+
*/
|
|
233
|
+
export interface UpdateEventChannelInput {
|
|
234
|
+
name?: string;
|
|
235
|
+
description?: string;
|
|
236
|
+
enabled?: boolean;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Input for creating an event type
|
|
240
|
+
*/
|
|
241
|
+
export interface CreateEventTypeInput {
|
|
242
|
+
channelId: string;
|
|
243
|
+
code: string;
|
|
244
|
+
name: string;
|
|
245
|
+
description?: string;
|
|
246
|
+
payloadSchema?: Record<string, unknown>;
|
|
247
|
+
enabled?: boolean;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Input for updating an event type
|
|
251
|
+
*/
|
|
252
|
+
export interface UpdateEventTypeInput {
|
|
253
|
+
name?: string;
|
|
254
|
+
description?: string;
|
|
255
|
+
payloadSchema?: Record<string, unknown>;
|
|
256
|
+
enabled?: boolean;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Input for creating an event handler
|
|
260
|
+
*
|
|
261
|
+
* Handler types are business-friendly names:
|
|
262
|
+
* - SEND_EMAIL: Send email notification
|
|
263
|
+
* - SEND_SMS: Send SMS text message
|
|
264
|
+
* - SEND_PUSH: Send push notification
|
|
265
|
+
* - CALL_WEBHOOK: Call external API
|
|
266
|
+
* - ADVANCE_WORKFLOW: Move workflow forward
|
|
267
|
+
* - RUN_AUTOMATION: Execute business logic
|
|
268
|
+
*/
|
|
269
|
+
export interface CreateEventHandlerInput {
|
|
270
|
+
eventTypeId: string;
|
|
271
|
+
name: string;
|
|
272
|
+
description?: string;
|
|
273
|
+
handlerType: 'SEND_EMAIL' | 'SEND_SMS' | 'SEND_PUSH' | 'CALL_WEBHOOK' | 'ADVANCE_WORKFLOW' | 'RUN_AUTOMATION';
|
|
274
|
+
config: HandlerConfig;
|
|
275
|
+
priority?: number;
|
|
276
|
+
enabled?: boolean;
|
|
277
|
+
maxRetries?: number;
|
|
278
|
+
retryDelayMs?: number;
|
|
279
|
+
filterCondition?: string;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Input for updating an event handler
|
|
283
|
+
*/
|
|
284
|
+
export interface UpdateEventHandlerInput {
|
|
285
|
+
name?: string;
|
|
286
|
+
description?: string;
|
|
287
|
+
config?: HandlerConfig;
|
|
288
|
+
priority?: number;
|
|
289
|
+
enabled?: boolean;
|
|
290
|
+
maxRetries?: number;
|
|
291
|
+
retryDelayMs?: number;
|
|
292
|
+
filterCondition?: string;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Event channel with related data
|
|
296
|
+
*/
|
|
297
|
+
export interface EventChannelWithTypes {
|
|
298
|
+
id: string;
|
|
299
|
+
tenantId: string;
|
|
300
|
+
code: string;
|
|
301
|
+
name: string;
|
|
302
|
+
description: string | null;
|
|
303
|
+
enabled: boolean;
|
|
304
|
+
eventTypes: Array<{
|
|
305
|
+
id: string;
|
|
306
|
+
code: string;
|
|
307
|
+
name: string;
|
|
308
|
+
enabled: boolean;
|
|
309
|
+
}>;
|
|
310
|
+
createdAt: Date;
|
|
311
|
+
updatedAt: Date;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Event type with related data
|
|
315
|
+
*/
|
|
316
|
+
export interface EventTypeWithHandlers {
|
|
317
|
+
id: string;
|
|
318
|
+
tenantId: string;
|
|
319
|
+
channelId: string;
|
|
320
|
+
channel: {
|
|
321
|
+
code: string;
|
|
322
|
+
name: string;
|
|
323
|
+
};
|
|
324
|
+
code: string;
|
|
325
|
+
name: string;
|
|
326
|
+
description: string | null;
|
|
327
|
+
payloadSchema: Record<string, unknown> | null;
|
|
328
|
+
enabled: boolean;
|
|
329
|
+
handlers: Array<{
|
|
330
|
+
id: string;
|
|
331
|
+
name: string;
|
|
332
|
+
handlerType: string;
|
|
333
|
+
enabled: boolean;
|
|
334
|
+
}>;
|
|
335
|
+
createdAt: Date;
|
|
336
|
+
updatedAt: Date;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Event handler with related data
|
|
340
|
+
*/
|
|
341
|
+
export interface EventHandlerWithType {
|
|
342
|
+
id: string;
|
|
343
|
+
tenantId: string;
|
|
344
|
+
eventTypeId: string;
|
|
345
|
+
eventType: {
|
|
346
|
+
code: string;
|
|
347
|
+
name: string;
|
|
348
|
+
channel: {
|
|
349
|
+
code: string;
|
|
350
|
+
name: string;
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
name: string;
|
|
354
|
+
description: string | null;
|
|
355
|
+
handlerType: string;
|
|
356
|
+
config: HandlerConfig;
|
|
357
|
+
priority: number;
|
|
358
|
+
enabled: boolean;
|
|
359
|
+
maxRetries: number;
|
|
360
|
+
retryDelayMs: number;
|
|
361
|
+
filterCondition: string | null;
|
|
362
|
+
createdAt: Date;
|
|
363
|
+
updatedAt: Date;
|
|
364
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-Driven Workflow Types
|
|
3
|
+
*
|
|
4
|
+
* These types define the structure for a configurable event system
|
|
5
|
+
* where admins can define event types, channels, and handlers.
|
|
6
|
+
*
|
|
7
|
+
* Architecture:
|
|
8
|
+
* 1. EventChannel - Logical grouping of events (e.g., "CONTRACTS", "PAYMENTS")
|
|
9
|
+
* 2. EventType - Specific event types (e.g., "DOCUMENT_UPLOADED", "STEP_COMPLETED")
|
|
10
|
+
* 3. EventHandler - What to do when an event fires (send email, call webhook, etc.)
|
|
11
|
+
* 4. WorkflowEvent - Actual event instances (audit log)
|
|
12
|
+
* 5. EventHandlerExecution - Log of handler executions
|
|
13
|
+
*
|
|
14
|
+
* Handler types are business-friendly so non-technical admins can configure them:
|
|
15
|
+
* - SEND_EMAIL: Send an email to someone
|
|
16
|
+
* - SEND_SMS: Send a text message
|
|
17
|
+
* - SEND_PUSH: Send a push notification
|
|
18
|
+
* - CALL_WEBHOOK: Call an external API
|
|
19
|
+
* - ADVANCE_WORKFLOW: Move workflow forward
|
|
20
|
+
* - RUN_AUTOMATION: Execute business logic
|
|
21
|
+
*/
|
|
22
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valentine-efagene/qshelter-common",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.76",
|
|
4
4
|
"description": "Shared database schemas and utilities for QShelter services",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -29,11 +29,14 @@
|
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@aws-sdk/client-dynamodb": "^3.962.0",
|
|
32
|
+
"@aws-sdk/client-eventbridge": "^3.700.0",
|
|
32
33
|
"@aws-sdk/client-secrets-manager": "^3.500.0",
|
|
33
34
|
"@aws-sdk/client-sns": "^3.500.0",
|
|
35
|
+
"@aws-sdk/client-sqs": "^3.700.0",
|
|
34
36
|
"@aws-sdk/client-ssm": "^3.500.0",
|
|
35
37
|
"@aws-sdk/util-dynamodb": "^3.962.0",
|
|
36
38
|
"@prisma/client": "^7.0.0",
|
|
39
|
+
"axios": "^1.13.2",
|
|
37
40
|
"dotenv": "^17.2.3",
|
|
38
41
|
"prisma": "^7.0.0"
|
|
39
42
|
},
|
package/prisma/schema.prisma
CHANGED
|
@@ -211,12 +211,12 @@ enum OfferLetterStatus {
|
|
|
211
211
|
/// Handler Type - What kind of action the handler performs
|
|
212
212
|
/// These are business-friendly names that admins can understand
|
|
213
213
|
enum EventHandlerType {
|
|
214
|
-
SEND_EMAIL
|
|
215
|
-
SEND_SMS
|
|
216
|
-
SEND_PUSH
|
|
217
|
-
CALL_WEBHOOK
|
|
214
|
+
SEND_EMAIL // Send an email notification to recipient(s)
|
|
215
|
+
SEND_SMS // Send an SMS text message
|
|
216
|
+
SEND_PUSH // Send a push notification
|
|
217
|
+
CALL_WEBHOOK // Call an external API/webhook
|
|
218
218
|
ADVANCE_WORKFLOW // Advance or complete a workflow step
|
|
219
|
-
RUN_AUTOMATION
|
|
219
|
+
RUN_AUTOMATION // Execute internal business logic
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
/// Actor Type - Who triggered an event
|
|
@@ -430,33 +430,33 @@ model Tenant {
|
|
|
430
430
|
// =============================================================================
|
|
431
431
|
|
|
432
432
|
model ApiKey {
|
|
433
|
-
id
|
|
434
|
-
tenantId
|
|
435
|
-
tenant
|
|
433
|
+
id String @id @default(cuid())
|
|
434
|
+
tenantId String
|
|
435
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
436
436
|
|
|
437
437
|
// Identification
|
|
438
|
-
name String
|
|
439
|
-
description String?
|
|
440
|
-
provider String
|
|
438
|
+
name String // Human-readable name (e.g., "Paystack Integration")
|
|
439
|
+
description String? @db.Text // Optional description
|
|
440
|
+
provider String // Partner/vendor name (e.g., "paystack", "flutterwave")
|
|
441
441
|
|
|
442
442
|
// Secret management (NEVER store raw secret in DB)
|
|
443
|
-
secretRef
|
|
443
|
+
secretRef String // AWS Secrets Manager ARN or name
|
|
444
444
|
|
|
445
445
|
// Permissions - scopes this API key is allowed to request
|
|
446
446
|
// Examples: ["contract:read", "payment:*", "property:read"]
|
|
447
|
-
scopes
|
|
447
|
+
scopes Json // JSON array of scope strings
|
|
448
448
|
|
|
449
449
|
// Lifecycle
|
|
450
|
-
enabled
|
|
451
|
-
expiresAt
|
|
452
|
-
lastUsedAt
|
|
453
|
-
revokedAt
|
|
454
|
-
revokedBy
|
|
450
|
+
enabled Boolean @default(true)
|
|
451
|
+
expiresAt DateTime? // Optional expiration date
|
|
452
|
+
lastUsedAt DateTime? // Updated on each token exchange
|
|
453
|
+
revokedAt DateTime? // Set when key is revoked
|
|
454
|
+
revokedBy String? // User ID who revoked
|
|
455
455
|
|
|
456
456
|
// Audit
|
|
457
|
-
createdBy
|
|
458
|
-
createdAt
|
|
459
|
-
updatedAt
|
|
457
|
+
createdBy String? // User ID who created
|
|
458
|
+
createdAt DateTime @default(now())
|
|
459
|
+
updatedAt DateTime @updatedAt
|
|
460
460
|
|
|
461
461
|
@@index([tenantId])
|
|
462
462
|
@@index([provider])
|
|
@@ -994,7 +994,7 @@ model PaymentMethodPhaseStep {
|
|
|
994
994
|
/// Step Event Attachment - Links event handlers to step template triggers
|
|
995
995
|
/// When a step transitions (complete, reject, etc.), attached handlers fire
|
|
996
996
|
model StepEventAttachment {
|
|
997
|
-
id String
|
|
997
|
+
id String @id @default(cuid())
|
|
998
998
|
stepId String
|
|
999
999
|
step PaymentMethodPhaseStep @relation(fields: [stepId], references: [id], onDelete: Cascade)
|
|
1000
1000
|
|
|
@@ -1104,7 +1104,6 @@ model Contract {
|
|
|
1104
1104
|
phases ContractPhase[]
|
|
1105
1105
|
documents ContractDocument[]
|
|
1106
1106
|
payments ContractPayment[]
|
|
1107
|
-
events ContractEvent[]
|
|
1108
1107
|
terminations ContractTermination[]
|
|
1109
1108
|
offerLetters OfferLetter[]
|
|
1110
1109
|
|
|
@@ -1121,6 +1120,9 @@ model Contract {
|
|
|
1121
1120
|
// Transfer requests where this contract is the target (created after approval)
|
|
1122
1121
|
incomingTransferRequests PropertyTransferRequest[] @relation("TargetContract")
|
|
1123
1122
|
|
|
1123
|
+
// Audit trail
|
|
1124
|
+
events ContractEvent[]
|
|
1125
|
+
|
|
1124
1126
|
@@index([tenantId])
|
|
1125
1127
|
@@index([propertyUnitId])
|
|
1126
1128
|
@@index([buyerId])
|
|
@@ -1212,6 +1214,44 @@ model ContractPhase {
|
|
|
1212
1214
|
@@map("contract_phases")
|
|
1213
1215
|
}
|
|
1214
1216
|
|
|
1217
|
+
// =============================================================================
|
|
1218
|
+
// CONTRACT EVENTS - Audit trail for contract lifecycle
|
|
1219
|
+
// =============================================================================
|
|
1220
|
+
// Tracks all significant events in a contract's lifecycle for audit, compliance,
|
|
1221
|
+
// and debugging. Unlike DomainEvent (which is for inter-service communication),
|
|
1222
|
+
// ContractEvent is purely for historical tracking and state machine transitions.
|
|
1223
|
+
// =============================================================================
|
|
1224
|
+
model ContractEvent {
|
|
1225
|
+
id String @id @default(cuid())
|
|
1226
|
+
contractId String
|
|
1227
|
+
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
1228
|
+
|
|
1229
|
+
// Event classification
|
|
1230
|
+
eventType String // STATE.TRANSITION, PHASE.ACTIVATED, PAYMENT.COMPLETED, CONTRACT.CREATED, etc.
|
|
1231
|
+
eventGroup String? // STATE_CHANGE, PAYMENT, DOCUMENT, NOTIFICATION (for filtering)
|
|
1232
|
+
|
|
1233
|
+
// For state transitions (optional - only populated for STATE.TRANSITION events)
|
|
1234
|
+
fromState String?
|
|
1235
|
+
toState String?
|
|
1236
|
+
trigger String?
|
|
1237
|
+
|
|
1238
|
+
// Event payload (all event-specific data)
|
|
1239
|
+
data Json?
|
|
1240
|
+
|
|
1241
|
+
// Actor tracking
|
|
1242
|
+
actorId String?
|
|
1243
|
+
actorType String? // USER, SYSTEM, WEBHOOK
|
|
1244
|
+
|
|
1245
|
+
// Timing
|
|
1246
|
+
occurredAt DateTime @default(now())
|
|
1247
|
+
|
|
1248
|
+
@@index([contractId])
|
|
1249
|
+
@@index([eventType])
|
|
1250
|
+
@@index([eventGroup])
|
|
1251
|
+
@@index([occurredAt])
|
|
1252
|
+
@@map("contract_events")
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1215
1255
|
// Steps within a DOCUMENTATION phase (FSM for document collection/approval)
|
|
1216
1256
|
model DocumentationStep {
|
|
1217
1257
|
id String @id @default(cuid())
|
|
@@ -1403,38 +1443,6 @@ model ContractDocument {
|
|
|
1403
1443
|
@@map("contract_documents")
|
|
1404
1444
|
}
|
|
1405
1445
|
|
|
1406
|
-
// Contract domain events (FSM transitions, payments, documents, etc.)
|
|
1407
|
-
model ContractEvent {
|
|
1408
|
-
id String @id @default(cuid())
|
|
1409
|
-
contractId String
|
|
1410
|
-
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
|
1411
|
-
|
|
1412
|
-
// Event classification
|
|
1413
|
-
eventType String // STATE.TRANSITION, PHASE.ACTIVATED, PAYMENT.COMPLETED, etc.
|
|
1414
|
-
eventGroup String? // STATE_CHANGE, PAYMENT, DOCUMENT, NOTIFICATION (for filtering)
|
|
1415
|
-
|
|
1416
|
-
// For state transitions (optional - only populated for STATE.TRANSITION events)
|
|
1417
|
-
fromState String?
|
|
1418
|
-
toState String?
|
|
1419
|
-
trigger String?
|
|
1420
|
-
|
|
1421
|
-
// Event payload (all event-specific data)
|
|
1422
|
-
data Json?
|
|
1423
|
-
|
|
1424
|
-
// Actor tracking
|
|
1425
|
-
actorId String?
|
|
1426
|
-
actorType String? // USER, SYSTEM, WEBHOOK
|
|
1427
|
-
|
|
1428
|
-
// Timing
|
|
1429
|
-
occurredAt DateTime @default(now())
|
|
1430
|
-
|
|
1431
|
-
@@index([contractId])
|
|
1432
|
-
@@index([eventType])
|
|
1433
|
-
@@index([eventGroup])
|
|
1434
|
-
@@index([occurredAt])
|
|
1435
|
-
@@map("contract_events")
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
1446
|
// =============================================================================
|
|
1439
1447
|
// OFFER LETTERS - Provisional and Final offer documents
|
|
1440
1448
|
// =============================================================================
|
|
@@ -1760,9 +1768,9 @@ model DocumentRequirementRule {
|
|
|
1760
1768
|
/// Event Channel - A logical grouping of events
|
|
1761
1769
|
/// Channels help organize events and route them to appropriate handlers
|
|
1762
1770
|
model EventChannel {
|
|
1763
|
-
id
|
|
1764
|
-
tenantId
|
|
1765
|
-
tenant
|
|
1771
|
+
id String @id @default(cuid())
|
|
1772
|
+
tenantId String
|
|
1773
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
1766
1774
|
|
|
1767
1775
|
/// Unique code for the channel (e.g., "CONTRACTS", "PAYMENTS")
|
|
1768
1776
|
code String
|
|
@@ -1772,7 +1780,7 @@ model EventChannel {
|
|
|
1772
1780
|
description String? @db.Text
|
|
1773
1781
|
|
|
1774
1782
|
/// Whether this channel is active
|
|
1775
|
-
enabled
|
|
1783
|
+
enabled Boolean @default(true)
|
|
1776
1784
|
|
|
1777
1785
|
/// Event types that belong to this channel
|
|
1778
1786
|
eventTypes EventType[]
|
|
@@ -1788,9 +1796,9 @@ model EventChannel {
|
|
|
1788
1796
|
/// Event Type - Defines a type of event that can occur
|
|
1789
1797
|
/// Each event type belongs to a channel and can have multiple handlers
|
|
1790
1798
|
model EventType {
|
|
1791
|
-
id
|
|
1792
|
-
tenantId
|
|
1793
|
-
tenant
|
|
1799
|
+
id String @id @default(cuid())
|
|
1800
|
+
tenantId String
|
|
1801
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
1794
1802
|
|
|
1795
1803
|
/// The channel this event type belongs to
|
|
1796
1804
|
channelId String
|
|
@@ -1828,9 +1836,9 @@ model EventType {
|
|
|
1828
1836
|
/// Event Handler - Defines what should happen when an event fires
|
|
1829
1837
|
/// Handlers can be internal (call a service), external (webhook), or workflow triggers
|
|
1830
1838
|
model EventHandler {
|
|
1831
|
-
id
|
|
1832
|
-
tenantId
|
|
1833
|
-
tenant
|
|
1839
|
+
id String @id @default(cuid())
|
|
1840
|
+
tenantId String
|
|
1841
|
+
tenant Tenant @relation(fields: [tenantId], references: [id], onDelete: Cascade)
|
|
1834
1842
|
|
|
1835
1843
|
/// The event type this handler responds to
|
|
1836
1844
|
eventTypeId String
|
|
@@ -2053,7 +2061,7 @@ model PropertyTransferRequest {
|
|
|
2053
2061
|
sourceTotalAmount Float? // Original contract total
|
|
2054
2062
|
targetTotalAmount Float? // New contract total (based on target property)
|
|
2055
2063
|
priceAdjustment Float? // Difference (positive = buyer owes more)
|
|
2056
|
-
paymentsMigrated Int?
|
|
2064
|
+
paymentsMigrated Int? // Number of payments migrated
|
|
2057
2065
|
|
|
2058
2066
|
// Result - new contract created after approval
|
|
2059
2067
|
targetContractId String?
|
|
@@ -2078,21 +2086,21 @@ model PropertyTransferRequest {
|
|
|
2078
2086
|
// =============================================================================
|
|
2079
2087
|
|
|
2080
2088
|
enum ApprovalRequestType {
|
|
2081
|
-
PROPERTY_TRANSFER
|
|
2082
|
-
PROPERTY_UPDATE
|
|
2083
|
-
USER_WORKFLOW
|
|
2084
|
-
CREDIT_CHECK
|
|
2089
|
+
PROPERTY_TRANSFER // Property unit transfer between contracts
|
|
2090
|
+
PROPERTY_UPDATE // Property/unit listing update requiring approval
|
|
2091
|
+
USER_WORKFLOW // User workflow step approval
|
|
2092
|
+
CREDIT_CHECK // Credit check result review
|
|
2085
2093
|
CONTRACT_TERMINATION // Contract termination approval
|
|
2086
|
-
REFUND_APPROVAL
|
|
2094
|
+
REFUND_APPROVAL // Refund request approval
|
|
2087
2095
|
}
|
|
2088
2096
|
|
|
2089
2097
|
enum ApprovalRequestStatus {
|
|
2090
|
-
PENDING
|
|
2091
|
-
IN_REVIEW
|
|
2092
|
-
APPROVED
|
|
2093
|
-
REJECTED
|
|
2094
|
-
CANCELLED
|
|
2095
|
-
EXPIRED
|
|
2098
|
+
PENDING // Awaiting review
|
|
2099
|
+
IN_REVIEW // Assigned to reviewer
|
|
2100
|
+
APPROVED // Approved by reviewer
|
|
2101
|
+
REJECTED // Rejected by reviewer
|
|
2102
|
+
CANCELLED // Cancelled by requestor
|
|
2103
|
+
EXPIRED // Auto-expired (if TTL configured)
|
|
2096
2104
|
}
|
|
2097
2105
|
|
|
2098
2106
|
enum ApprovalRequestPriority {
|
|
@@ -2119,7 +2127,7 @@ model ApprovalRequest {
|
|
|
2119
2127
|
|
|
2120
2128
|
// Request metadata
|
|
2121
2129
|
title String @db.VarChar(255) // Human-readable title for the request
|
|
2122
|
-
description String? @db.Text
|
|
2130
|
+
description String? @db.Text // Detailed description
|
|
2123
2131
|
|
|
2124
2132
|
// Payload for any additional context (JSON)
|
|
2125
2133
|
payload Json? // Flexible data storage for type-specific details
|
|
@@ -2137,7 +2145,7 @@ model ApprovalRequest {
|
|
|
2137
2145
|
reviewedBy User? @relation("ApprovalReviewer", fields: [reviewedById], references: [id])
|
|
2138
2146
|
|
|
2139
2147
|
// Review details
|
|
2140
|
-
reviewNotes String?
|
|
2148
|
+
reviewNotes String? @db.Text // Reviewer's notes/comments
|
|
2141
2149
|
decision ApprovalDecision? // APPROVED, REJECTED, REQUEST_CHANGES
|
|
2142
2150
|
|
|
2143
2151
|
// Expiration
|