Skip to main content

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.* matches crm.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