Uniconnect Notification System (Generic Implementation Plan)
Goal
Build a but fully generic notification engine that supports:
- Any event source (CRM, system, workflow, AI, integrations)
- Config-driven routing (no hardcoded logic)
- Multiple channels (in-app, web push, email, SMS)
- Payload-based user targeting
- Role + expression-based recipient resolution
- Read/unread tracking for in-app notifications
1. Core Design Principles
1.1 Event-Agnostic System
The notification system does NOT know:
- CRM
- workflows
- AI agents
- system internals
It only understands:
event + payload + config → notifications
1.2 Config-Driven Behavior
All behavior is defined via configuration:
- who gets notified
- how users are resolved
- which channels are used
- how messages are rendered
1.3 Payload-Centric Targeting
Recipients are derived from event payload using:
- field paths
- roles
- expressions
1.4 Async Delivery
All external channels are async via queue.
2. Architecture
Event Producer
↓
Notification Service (notify())
↓
Config Matcher
↓
Recipient Resolver
↓
Template Renderer
↓
Notification Store
↓
Queue Dispatcher
↓
Channel Adapters
3. Core Data Model (Version)
3.1 Notification Config
Defines routing rules.
CREATE TABLE notification_configs (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
event_pattern VARCHAR(255) NOT NULL,
enabled BOOLEAN DEFAULT TRUE,
conditions JSON, -- optional filters
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3.2 Notification Targets
Defines how to resolve recipients.
CREATE TABLE notification_config_targets (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
config_id BIGINT NOT NULL,
type VARCHAR(50) NOT NULL,
-- payload_field | payload_path | role | expression
value TEXT NOT NULL,
FOREIGN KEY (config_id) REFERENCES notification_configs(id)
);
3.3 Notification Channels
CREATE TABLE notification_channels (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
code VARCHAR(50) UNIQUE NOT NULL,
type VARCHAR(50),
enabled BOOLEAN DEFAULT TRUE
);
3.4 Notification Records
CREATE TABLE notifications (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
event_code VARCHAR(255),
title TEXT,
body TEXT,
payload JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3.5 Delivery Tracking (In-App + Others)
CREATE TABLE notification_deliveries (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
notification_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
channel_code VARCHAR(50),
is_read BOOLEAN DEFAULT FALSE,
read_at TIMESTAMP NULL,
status VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
4. Core API Design
4.1 Trigger Notification (Single Entry Point)
notificationService.notify({
event: "crm.ticket.assigned",
payload: {
ticket: {
id: 101,
assignedTo: { id: 55 }
}
},
context: {
tenantId: 1,
actorId: 10
}
});
5. Internal Processing Flow
Step 1: Match Configs
findConfigs(event) → wildcard match
Example:
crm.ticket.*matchescrm.ticket.assigned
Step 2: Evaluate Conditions (optional)
{
"ticket.priority": "high"
}
Skip config if condition fails.
Step 3: Resolve Recipients
Supported strategies:
3.1 payload_field
{ "type": "payload_field", "value": "assignedToId" }
3.2 payload_path
{ "type": "payload_path", "value": "ticket.assignedTo.id" }
3.3 role
{ "type": "role", "value": "support_agent" }
3.4 expression
{ "type": "expression", "value": "payload.ticket.priority === 'high' ? payload.ticket.assignedTo.id : null" }
Step 4: Deduplicate Users
- merge all resolved users
- remove duplicates
- remove nulls
Step 5: Render Notification
Simple template:
Ticket #{{ticket.id}} assigned to you
Step 6: Store Notification
Create single record:
- event
- payload
- rendered message
Step 7: Create Delivery Records
One per user per channel:
notification_deliveries
Step 8: Queue Channel Delivery
Push jobs:
- email queue
- sms queue
- push queue
- websocket dispatcher
6. Channel Adapter Interface
interface NotificationChannel {
send(notification, user): Promise<void>;
}
Implementations:
- InAppChannel
- EmailChannel
- SMSChannel
- WebPushChannel
7. Event Pattern Matching
Supports:
- exact match:
crm.ticket.assigned - wildcard:
crm.ticket.* - global:
*
8. Recipient Resolver
class RecipientResolver {
resolve(targets, payload) {
let users = [];
for (const t of targets) {
switch (t.type) {
case "payload_field":
users.push(payload[t.value]);
break;
case "payload_path":
users.push(resolvePath(payload, t.value));
break;
case "role":
users.push(getUsersByRole(t.value));
break;
case "expression":
users.push(evalExpression(t.value, payload));
break;
}
}
return deduplicate(users.flat());
}
}
9. In-App Notification Requirements
Must support:
- unread count
- mark as read
- mark all as read
- click tracking
- real-time updates (WebSocket/SSE)
10. UI Requirements
User Side
- notification bell
- list view
- unread badge
- CTA button click
Admin Side
- create config
- map event → targets → channels
- simple rule editor
Upgrade Guide
Uniconnect Upgrade for Sumathi
Module Design
Ticket includes slaPausedAt to track when the SLA timer is paused during waiting statuses.
Workflow Design
1. Ticket Creation Workflow
2. Group Change Workflow
3. Status Change Workflow
4. SLA Monitoring Workflow
5. Ticket Closure Workflow
6. Reopen Workflow
Reports and Dashboards
Dimensions
- Ticket Type
- Category
- Priority
- Status
- Assigned Group
- Assigned User
- SLA Status
- Created Date
- Closed Date
Measures
- Average Resolution Time
- Average First Response Time
- Average L1 Handling Time
- Average L2 Handling Time
- Average L3 Handling Time
- SLA Compliance Percentage
- Breach Count
- Escalation Count
- Reopen Rate
- Ticket Volume Trends
- Historical Comparison Trends