@valentine-efagene/qshelter-common 2.0.69 → 2.0.72

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.
@@ -7,121 +7,162 @@
7
7
  * Architecture:
8
8
  * 1. EventChannel - Logical grouping of events (e.g., "CONTRACTS", "PAYMENTS")
9
9
  * 2. EventType - Specific event types (e.g., "DOCUMENT_UPLOADED", "STEP_COMPLETED")
10
- * 3. EventHandler - What to do when an event fires (webhook, internal call, etc.)
10
+ * 3. EventHandler - What to do when an event fires (send email, call webhook, etc.)
11
11
  * 4. WorkflowEvent - Actual event instances (audit log)
12
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
13
21
  */
14
22
  export type { EventHandlerType, ActorType, WorkflowEventStatus, ExecutionStatus, } from '../../generated/client/enums';
15
23
  /**
16
- * Configuration for INTERNAL handler type
17
- * Calls an internal service method
24
+ * Configuration for SEND_EMAIL handler type
25
+ * Sends an email notification to specified recipients
18
26
  */
19
- export interface InternalHandlerConfig {
20
- type: 'INTERNAL';
21
- /** Service name (e.g., "contract", "payment") */
22
- service: string;
23
- /** Method to call on the service */
24
- method: string;
25
- /** Optional payload transformation (JSONPath mapping) */
26
- payloadMapping?: Record<string, string>;
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';
27
50
  }
28
51
  /**
29
- * Configuration for WEBHOOK handler type
30
- * Sends HTTP request to external URL
52
+ * Configuration for SEND_SMS handler type
53
+ * Sends an SMS text message
31
54
  */
32
- export interface WebhookHandlerConfig {
33
- type: 'WEBHOOK';
34
- /** Target URL */
35
- url: string;
36
- /** HTTP method */
37
- method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
38
- /** Optional headers */
39
- headers?: Record<string, string>;
40
- /** Optional payload transformation */
41
- payloadMapping?: Record<string, string>;
42
- /** Timeout in milliseconds */
43
- timeoutMs?: number;
44
- /** Whether to include event metadata in request */
45
- includeMetadata?: boolean;
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>;
46
72
  }
47
73
  /**
48
- * Configuration for WORKFLOW handler type
49
- * Triggers or advances a workflow
74
+ * Configuration for SEND_PUSH handler type
75
+ * Sends a push notification to user's device
50
76
  */
51
- export interface WorkflowHandlerConfig {
52
- type: 'WORKFLOW';
53
- /** Target workflow/phase ID */
54
- workflowId?: string;
55
- phaseId?: string;
56
- stepId?: string;
57
- /** Action to perform */
58
- action: 'start' | 'advance' | 'complete' | 'fail' | 'skip';
59
- /** Optional data to pass */
60
- data?: Record<string, unknown>;
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>;
61
98
  }
62
99
  /**
63
- * Configuration for NOTIFICATION handler type
64
- * Sends notifications via various channels (internal handling)
100
+ * Configuration for CALL_WEBHOOK handler type
101
+ * Calls an external API endpoint
65
102
  */
66
- export interface NotificationHandlerConfig {
67
- type: 'NOTIFICATION';
68
- /** Notification template ID or inline template */
69
- template: string;
70
- /** Channels to send through */
71
- channels: ('email' | 'sms' | 'push' | 'in_app')[];
72
- /** Recipients (can use payload variables like $.user.email) */
73
- recipients?: {
74
- email?: string[];
75
- phone?: string[];
76
- userId?: string[];
77
- };
78
- /** Priority */
79
- priority?: 'low' | 'normal' | 'high' | 'urgent';
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;
80
118
  }
81
119
  /**
82
- * Configuration for SNS handler type
83
- * Publishes to SNS topic, which triggers the notification-service via SQS
84
- * Uses the NotificationEvent format expected by notification-service
120
+ * Configuration for ADVANCE_WORKFLOW handler type
121
+ * Advances or modifies a workflow step
85
122
  */
86
- export interface SnsHandlerConfig {
87
- type: 'SNS';
88
- /** SNS Topic ARN (optional - defaults to notifications topic) */
89
- topicArn?: string;
90
- /** Notification type (from NotificationType enum) */
91
- notificationType: string;
92
- /** Notification channel (email, sms, push) */
93
- channel: 'email' | 'sms' | 'push';
94
- /**
95
- * Payload mapping - maps event payload to notification payload
96
- * Uses JSONPath-like expressions (e.g., $.user.email -> to_email)
97
- */
98
- payloadMapping?: Record<string, string>;
123
+ export interface AdvanceWorkflowHandlerConfig {
124
+ type: 'ADVANCE_WORKFLOW';
125
+ /** What action to take */
126
+ action: 'complete_step' | 'skip_step' | 'fail_step' | 'activate_phase';
99
127
  /**
100
- * Static payload fields to merge with mapped payload
128
+ * Step ID path in event payload (if action targets a specific step)
129
+ * Example: "$.stepId"
101
130
  */
102
- staticPayload?: Record<string, unknown>;
131
+ stepIdPath?: string;
103
132
  /**
104
- * Email recipient field path in the event payload (e.g., $.user.email)
133
+ * Phase ID path in event payload (if action targets a phase)
134
+ * Example: "$.phaseId"
105
135
  */
106
- recipientPath?: string;
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;
107
147
  }
108
148
  /**
109
- * Configuration for SCRIPT handler type
110
- * Executes custom logic
149
+ * Configuration for RUN_AUTOMATION handler type
150
+ * Executes internal business logic
111
151
  */
112
- export interface ScriptHandlerConfig {
113
- type: 'SCRIPT';
114
- /** Script language */
115
- language: 'jsonata' | 'javascript';
116
- /** The script/expression to execute */
117
- script: string;
118
- /** Timeout in milliseconds */
119
- timeoutMs?: number;
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>;
120
161
  }
121
162
  /**
122
163
  * Union type for all handler configurations
123
164
  */
124
- export type HandlerConfig = InternalHandlerConfig | WebhookHandlerConfig | WorkflowHandlerConfig | NotificationHandlerConfig | SnsHandlerConfig | ScriptHandlerConfig;
165
+ export type HandlerConfig = SendEmailHandlerConfig | SendSmsHandlerConfig | SendPushHandlerConfig | CallWebhookHandlerConfig | AdvanceWorkflowHandlerConfig | RunAutomationHandlerConfig;
125
166
  /**
126
167
  * Input for emitting an event
127
168
  */
@@ -216,12 +257,20 @@ export interface UpdateEventTypeInput {
216
257
  }
217
258
  /**
218
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
219
268
  */
220
269
  export interface CreateEventHandlerInput {
221
270
  eventTypeId: string;
222
271
  name: string;
223
272
  description?: string;
224
- handlerType: 'INTERNAL' | 'WEBHOOK' | 'WORKFLOW' | 'NOTIFICATION' | 'SCRIPT';
273
+ handlerType: 'SEND_EMAIL' | 'SEND_SMS' | 'SEND_PUSH' | 'CALL_WEBHOOK' | 'ADVANCE_WORKFLOW' | 'RUN_AUTOMATION';
225
274
  config: HandlerConfig;
226
275
  priority?: number;
227
276
  enabled?: boolean;
@@ -7,8 +7,16 @@
7
7
  * Architecture:
8
8
  * 1. EventChannel - Logical grouping of events (e.g., "CONTRACTS", "PAYMENTS")
9
9
  * 2. EventType - Specific event types (e.g., "DOCUMENT_UPLOADED", "STEP_COMPLETED")
10
- * 3. EventHandler - What to do when an event fires (webhook, internal call, etc.)
10
+ * 3. EventHandler - What to do when an event fires (send email, call webhook, etc.)
11
11
  * 4. WorkflowEvent - Actual event instances (audit log)
12
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
13
21
  */
14
22
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valentine-efagene/qshelter-common",
3
- "version": "2.0.69",
3
+ "version": "2.0.72",
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",
@@ -0,0 +1,28 @@
1
+ /*
2
+ Warnings:
3
+
4
+ - The values [INTERNAL,WEBHOOK,WORKFLOW,NOTIFICATION,SNS,SCRIPT] on the enum `event_handlers_handlerType` will be removed. If these variants are still used in the database, this will fail.
5
+
6
+ */
7
+
8
+ -- First, migrate existing data to new enum values
9
+ -- INTERNAL -> RUN_AUTOMATION (internal service calls are now automations)
10
+ -- WEBHOOK -> CALL_WEBHOOK (external API calls)
11
+ -- WORKFLOW -> ADVANCE_WORKFLOW (workflow state changes)
12
+ -- NOTIFICATION -> SEND_EMAIL (general notifications default to email)
13
+ -- SNS -> SEND_EMAIL (SNS was for email notifications)
14
+ -- SCRIPT -> RUN_AUTOMATION (custom scripts are automations)
15
+
16
+ -- Add new enum values first (MySQL requires this approach)
17
+ ALTER TABLE `event_handlers` MODIFY `handlerType` ENUM('INTERNAL', 'WEBHOOK', 'WORKFLOW', 'NOTIFICATION', 'SNS', 'SCRIPT', 'SEND_EMAIL', 'SEND_SMS', 'SEND_PUSH', 'CALL_WEBHOOK', 'ADVANCE_WORKFLOW', 'RUN_AUTOMATION') NOT NULL;
18
+
19
+ -- Migrate data
20
+ UPDATE `event_handlers` SET `handlerType` = 'RUN_AUTOMATION' WHERE `handlerType` = 'INTERNAL';
21
+ UPDATE `event_handlers` SET `handlerType` = 'CALL_WEBHOOK' WHERE `handlerType` = 'WEBHOOK';
22
+ UPDATE `event_handlers` SET `handlerType` = 'ADVANCE_WORKFLOW' WHERE `handlerType` = 'WORKFLOW';
23
+ UPDATE `event_handlers` SET `handlerType` = 'SEND_EMAIL' WHERE `handlerType` = 'NOTIFICATION';
24
+ UPDATE `event_handlers` SET `handlerType` = 'SEND_EMAIL' WHERE `handlerType` = 'SNS';
25
+ UPDATE `event_handlers` SET `handlerType` = 'RUN_AUTOMATION' WHERE `handlerType` = 'SCRIPT';
26
+
27
+ -- Now remove old enum values
28
+ ALTER TABLE `event_handlers` MODIFY `handlerType` ENUM('SEND_EMAIL', 'SEND_SMS', 'SEND_PUSH', 'CALL_WEBHOOK', 'ADVANCE_WORKFLOW', 'RUN_AUTOMATION') NOT NULL;
@@ -84,6 +84,15 @@ enum StepStatus {
84
84
  AWAITING_REVIEW // Submitted, waiting for admin/system review
85
85
  }
86
86
 
87
+ /// When a step event attachment should trigger
88
+ enum StepTrigger {
89
+ ON_COMPLETE // When step is approved/completed
90
+ ON_REJECT // When step is rejected
91
+ ON_SUBMIT // When step is submitted for review
92
+ ON_RESUBMIT // When step is resubmitted after rejection
93
+ ON_START // When step transitions to IN_PROGRESS
94
+ }
95
+
87
96
  enum InstallmentStatus {
88
97
  PENDING
89
98
  PAID
@@ -190,13 +199,14 @@ enum OfferLetterStatus {
190
199
  // =============================================================================
191
200
 
192
201
  /// Handler Type - What kind of action the handler performs
202
+ /// These are business-friendly names that admins can understand
193
203
  enum EventHandlerType {
194
- INTERNAL // Call an internal service method
195
- WEBHOOK // Send a webhook to an external URL
196
- WORKFLOW // Trigger or advance a workflow
197
- NOTIFICATION // Send a notification (email, SMS, push) - internal
198
- SNS // Publish to SNS topic (for notification-service)
199
- SCRIPT // Execute a custom script/expression
204
+ SEND_EMAIL // Send an email notification to recipient(s)
205
+ SEND_SMS // Send an SMS text message
206
+ SEND_PUSH // Send a push notification
207
+ CALL_WEBHOOK // Call an external API/webhook
208
+ ADVANCE_WORKFLOW // Advance or complete a workflow step
209
+ RUN_AUTOMATION // Execute internal business logic
200
210
  }
201
211
 
202
212
  /// Actor Type - Who triggered an event
@@ -946,10 +956,42 @@ model PaymentMethodPhaseStep {
946
956
  createdAt DateTime @default(now())
947
957
  updatedAt DateTime @updatedAt
948
958
 
959
+ // Event attachments - handlers that fire on step transitions
960
+ eventAttachments StepEventAttachment[]
961
+
949
962
  @@index([phaseId])
950
963
  @@map("payment_method_phase_steps")
951
964
  }
952
965
 
966
+ /// Step Event Attachment - Links event handlers to step template triggers
967
+ /// When a step transitions (complete, reject, etc.), attached handlers fire
968
+ model StepEventAttachment {
969
+ id String @id @default(cuid())
970
+ stepId String
971
+ step PaymentMethodPhaseStep @relation(fields: [stepId], references: [id], onDelete: Cascade)
972
+
973
+ /// When this handler should fire
974
+ trigger StepTrigger
975
+
976
+ /// The event handler to execute
977
+ handlerId String
978
+ handler EventHandler @relation(fields: [handlerId], references: [id], onDelete: Cascade)
979
+
980
+ /// Order of execution (lower = first)
981
+ priority Int @default(100)
982
+
983
+ /// Whether this attachment is active
984
+ enabled Boolean @default(true)
985
+
986
+ createdAt DateTime @default(now())
987
+ updatedAt DateTime @updatedAt
988
+
989
+ @@unique([stepId, handlerId, trigger])
990
+ @@index([stepId])
991
+ @@index([handlerId])
992
+ @@map("step_event_attachments")
993
+ }
994
+
953
995
  // Required document within a DOCUMENTATION phase
954
996
  model PaymentMethodPhaseDocument {
955
997
  id String @id @default(cuid())
@@ -1788,6 +1830,9 @@ model EventHandler {
1788
1830
  /// Handler execution logs
1789
1831
  executions EventHandlerExecution[]
1790
1832
 
1833
+ /// Step attachments - steps that have attached this handler
1834
+ stepAttachments StepEventAttachment[]
1835
+
1791
1836
  createdAt DateTime @default(now())
1792
1837
  updatedAt DateTime @updatedAt
1793
1838