Communication Recipient Targeting - Proposal Summary
Executive Summary
Problem: The current communication system can only send messages to ALL business users. There's no way for businesses to control WHO receives specific communication types (low stock alerts, reports, etc.) without modifying code.
Solution: Add flexible recipient targeting that allows businesses to configure who receives each communication type through:
- Role-based targeting (e.g., all inventory managers)
- Custom groups (e.g., "Finance Team" with mixed users + external emails)
- Ad-hoc recipients (e.g., specific emails or phone numbers)
- Combinations of all the above
Impact:
- Businesses control recipients via admin UI (no code changes)
- Support for external contacts (suppliers, accountants, etc.)
- Full audit trail for compliance
- Scalable and flexible for any communication type
Current State vs Proposed State
Current State ❌
Low Stock Alert Event → Handler → Send to ALL business users
Problems:
- Can't filter by role
- Can't send to external contacts
- Can't create custom distribution lists
- Requires code changes to modify recipients
- No audit trail
Proposed State ✅
Low Stock Alert Event → RecipientResolverService → Query Rules → Resolve Recipients
↓
Rules: inventory_manager role
+ Purchasing Team group
+ Owner's phone (ad-hoc)
↓
Send to resolved list
↓
Log recipient selection
Benefits:
- Filter by roles, groups, or ad-hoc
- Include external contacts
- Configurable via admin UI
- Full audit trail
- Per-business customization
Proposed Database Schema
4 New Tables
1. communication_recipient_group
Purpose: Custom groups businesses create (e.g., "Finance Team", "Purchasing Dept")
CREATE TABLE communication_recipient_group (
id UUID PRIMARY KEY,
business_id UUID NOT NULL,
name VARCHAR NOT NULL, -- "Finance Team"
description TEXT,
is_active BOOLEAN DEFAULT TRUE,
UNIQUE(business_id, name)
);
2. communication_group_member
Purpose: Members in groups (can be users, emails, or phone numbers)
CREATE TYPE recipient_member_type AS ENUM (
'business_user', -- Internal user
'email', -- External email
'phone', -- Phone for SMS
'whatsapp' -- WhatsApp number
);
CREATE TABLE communication_group_member (
id UUID PRIMARY KEY,
group_id UUID NOT NULL,
member_type recipient_member_type,
-- Polymorphic: only one filled based on type
business_user_id UUID,
email_address VARCHAR,
phone_number VARCHAR,
display_name VARCHAR,
is_active BOOLEAN DEFAULT TRUE
);
3. business_communication_recipient_rule
Purpose: Define WHO receives each communication type/channel
CREATE TYPE recipient_targeting_type AS ENUM (
'role', -- All users with specific role
'group', -- All members of custom group
'ad_hoc_email', -- Single email
'ad_hoc_phone', -- Single phone
'ad_hoc_whatsapp' -- Single WhatsApp
);
CREATE TABLE business_communication_recipient_rule (
id UUID PRIMARY KEY,
business_id UUID NOT NULL,
communication_type communication_type,
channel communication_channel,
targeting_type recipient_targeting_type,
-- Polymorphic: only one filled based on targeting_type
role_name unique_role_names,
group_id UUID,
ad_hoc_email VARCHAR,
ad_hoc_phone VARCHAR,
ad_hoc_whatsapp VARCHAR,
priority INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT TRUE
);
4. communication_recipient_log
Purpose: Audit trail of who was selected and why
CREATE TABLE communication_recipient_log (
id UUID PRIMARY KEY,
communication_id UUID,
recipient_contact VARCHAR,
selection_method VARCHAR, -- 'role', 'group', 'ad_hoc'
selection_source_id UUID, -- Which rule selected them
selected_at TIMESTAMPTZ
);
Real-World Examples
Example 1: Low Stock Alerts
Business Requirement: "Send low stock alerts to our 2 inventory managers, our purchasing team (3 people + 1 supplier email), and owner's mobile phone"
Configuration:
// Rule 1: Role-based
{
targetingType: 'role',
roleName: 'inventory_manager',
channel: 'email'
}
// Rule 2: Group-based
{
targetingType: 'group',
groupId: 'purchasing-team-uuid',
channel: 'email'
}
// Group contains:
// - 3 business users (internal staff)
// - 1 email: 'supplier@vendor.com' (external)
// Rule 3: Ad-hoc phone
{
targetingType: 'ad_hoc_phone',
phone: '+1234567890',
name: 'Owner Mobile',
channel: 'sms'
}
Result:
- Email sent to: 2 inventory managers + 3 purchasing staff + supplier
- SMS sent to: Owner's phone
- All configured via admin UI, no code changes!
Example 2: Daily Sales Reports
Business A: "Send reports to our Finance Team group only" Business B: "Send reports to owner + admin + external accountant"
Each business configures their own rules - no code changes needed!
Example 3: Emergency Alerts (Multi-Channel)
Requirement: "Send emergency alerts via BOTH email AND SMS to owners + admins + security service"
Configuration:
// Email rules
{ targetingType: 'role', roleName: 'owner', channel: 'email' }
{ targetingType: 'role', roleName: 'admin', channel: 'email' }
// SMS rules
{ targetingType: 'role', roleName: 'owner', channel: 'sms' }
{ targetingType: 'role', roleName: 'admin', channel: 'sms' }
{ targetingType: 'ad_hoc_phone', phone: '+1-555-SECURITY', channel: 'sms' }
Key Architecture Components
RecipientResolverService
Core service that resolves rules to actual recipients.
Flow:
- Query all active rules for business + type + channel
- For each rule:
- Role → Query all business users with that role
- Group → Query all group members (users + external contacts)
- Ad-hoc → Use the email/phone directly
- Deduplicate recipients (same person via multiple rules)
- Return final list
Usage in Handlers:
// Before
const users = await this.businessUsersService.findByBusinessId(businessId);
// After
const recipients = await this.recipientResolverService.resolveRecipients(
businessId,
'low_stock_alert',
'email'
);
Admin UI Mockup
Recipient Groups Management
╔══════════════════════════════════════════════════════════╗
║ Recipient Groups [+ New Group] ║
╠══════════════════════════════════════════════════════════╣
║ Name Members Created Actions ║
║ ─────────────────────────────────────────────────────── ║
║ Finance Team 5 2 days ago Edit Delete ║
║ Purchasing Dept 7 1 week ago Edit Delete ║
║ Emergency Team 3 1 month ago Edit Delete ║
╚══════════════════════════════════════════════════════════╝
╔══════════════════════════════════════════════════════════╗
║ Finance Team - Members [+ Add Member]║
╠══════════════════════════════════════════════════════════╣
║ Name Type Contact ║
║ ─────────────────────────────────────────────────────── ║
║ John Doe Business User john@company.com ║
║ Jane Smith Business User jane@company.com ║
║ External CPA Email cpa@firm.com ║
║ Owner Mobile Phone +1234567890 ║
╚══════════════════════════════════════════════════════════╝
Communication Rules Configuration
╔══════════════════════════════════════════════════════════════════╗
║ Communication Rules - Low Stock Alerts ║
╠══════════════════════════════════════════════════════════════════╣
║ Channel: Email ║
║ ───────────────────────────────────────────────────────────────║
║ [✓] Send to: Role = Inventory Manager ║
║ [✓] Send to: Group = Purchasing Team ║
║ ║
║ Channel: SMS ║
║ ───────────────────────────────────────────────────────────────║
║ [✓] Send to: Phone = +1234567890 (Owner Mobile) ║
║ ║
║ [Preview Recipients] [Save Rules] ║
╚══════════════════════════════════════════════════════════════════╝
Preview Recipients (7 total):
• john@company.com (via role: inventory_manager)
• jane@company.com (via role: inventory_manager)
• staff1@company.com (via group: Purchasing Team)
• staff2@company.com (via group: Purchasing Team)
• staff3@company.com (via group: Purchasing Team)
• supplier@vendor.com (via group: Purchasing Team)
• +1234567890 (via ad-hoc: Owner Mobile)
Implementation Roadmap
Phase 1: Database (1 day)
- ✅ Run migration to create 4 new tables
- ✅ Verify constraints and indexes
Phase 2: Backend - Repositories & Services (5-7 days)
- Create repositories for groups, rules, and logs
- Create RecipientResolverService (core logic)
- Create management services
- Write comprehensive tests
Phase 3: Backend - APIs (2-3 days)
- Create group management endpoints
- Create rule management endpoints
- Create preview endpoint
- Add authentication/authorization
Phase 4: Update Handlers (2 days)
- Update low stock alert handler
- Update other communication handlers
- Add recipient logging
Phase 5: Frontend UI (5-7 days)
- Group management pages
- Rule configuration pages
- Integration with settings
Phase 6: Testing & Deployment (3-4 days)
- Unit, integration, and e2e tests
- Deploy to staging
- User acceptance testing
- Production deployment
Total Estimate: 22-29 days (4-6 weeks)
Migration Strategy
Zero Downtime Deployment
- Add tables (non-breaking change)
- Deploy services (not used yet)
- Deploy APIs (not used yet)
- Deploy UI (allow businesses to configure)
- Update handlers one at a time (gradual rollout)
- Create default rules for existing businesses
Fallback Behavior
If no rules configured → Use existing behavior (send to all business users)
Risk Assessment
| Risk | Mitigation |
|---|---|
| Performance impact on recipient resolution | Add caching, optimize queries, add indexes |
| Complex configuration confuses users | Simple UI, preview feature, good defaults |
| Breaking existing communications | Thorough testing, gradual rollout, fallback behavior |
| Data migration issues | Test migration in staging, backup before production |
Success Metrics
Functional
- ✅ 100% of communication types support recipient targeting
- ✅ Businesses can configure rules without developer help
- ✅ External contacts receive communications
- ✅ Audit trail captured for all recipient selections
Performance
- ✅ Recipient resolution < 500ms
- ✅ No impact on communication send time
- ✅ Database queries optimized (< 100ms)
User Satisfaction
- ✅ Admin UI is intuitive (< 5 min to configure first group)
- ✅ Preview feature helps users understand before saving
- ✅ 80%+ of businesses use custom groups within 1 month
Next Steps
- Review this proposal with the team
- Approve database schema changes
- Create Jira tickets from implementation checklist
- Assign ownership of each phase
- Begin Phase 1 (database migration)
Questions & Answers
Q: What if a business doesn't configure any rules?
A: Fallback to existing behavior (send to all business users). We can also create sensible default rules during onboarding.
Q: Can recipients opt-out of certain communication types?
A: Not in initial implementation. This can be added as a future enhancement using the existing communication_preference table.
Q: How do we prevent spamming external contacts?
A: The existing rate limiting in business_communication_config still applies. We can also add recipient-level rate limiting in the future.
Q: What if a user is in multiple roles/groups that match?
A: They receive the communication once (deduplication in RecipientResolverService).
Q: Can we test this before going live?
A: Yes! The preview endpoint allows businesses to see exactly who will receive before saving rules.
Conclusion
This recipient targeting system extends the existing communication infrastructure with flexible, business-controlled recipient management. It solves the core problem of "who receives what" while maintaining backward compatibility and providing a clear migration path.
The polymorphic design supports current needs (roles, groups, ad-hoc) while allowing future extensions (location-based, time-based, escalation chains) without schema changes.
Recommendation: Approve and proceed with Phase 1 (database migration).
Appendix: Full Documentation
For detailed implementation guidance, see: