Back to landing page
Last updated: 09 Jul 2026, 10:15 AM
Documentation

Notification Flow

Notification types, settings, delivery, and queue flow.

Phase 1 Notification Flow

This document defines the proposed notification flow for the BCI app and admin portal before implementation.

No code changes are assumed from this document alone.

Objective

Build a notification module that supports:

  1. app push notification delivery
  2. in-app notification listing/history
  3. member-level notification preferences from App Settings
  4. system-triggered notifications from existing modules
  5. admin-triggered general notifications

Scope

Phase 1 covers:

  • notification data model
  • notification preference model
  • device token registration
  • notification creation flow
  • recipient resolution flow
  • app settings API flow
  • app notification inbox API flow
  • admin general notification API flow

Current Implementation Status

Current backend status:

Done

  • notification master/data tables
  • notification type seeder
  • member-level notification settings
  • member device token registration
  • app notification inbox list
  • mark one notification as read
  • mark all notifications as read
  • admin general notification create API
  • app general notification create API
  • admin notification logs API
  • queued recipient fan-out for large audiences
  • Firebase FCM push delivery integration
  • package-backed Firebase integration using kreait/laravel-firebase
  • Firebase service methods for:
    • single token send
    • multicast send
    • batch send with mixed payloads
  • system trigger wiring for:
    • GENERAL
    • EVENT
    • REFERRAL
    • SESSION
    • BUSINESS_EXCHANGE
    • NEW_MEMBER_JOINED
    • EVENT_ATTENDANCE
    • SUBSCRIPTION
    • CHAPTER_ASSIGNED

Not done yet

  • GRIEVANCE status-change trigger flow
  • notification detail GET /notifications/{notificationRecipient} API
  • end-to-end production verification with real Firebase credentials and mobile devices

Important:

  • real mobile push delivery is now integrated through Firebase FCM when FIREBASE_PUSH_ENABLED=true
  • if Firebase push is disabled, backend skips external push and keeps internal notification flow working for development/testing
  • Firebase setup details are documented in firebase-push-notification-setup.md

Phase 1 does not require:

  • website notifications
  • email notification fallback
  • SMS notification fallback
  • notification scheduling UI
  • rich campaign/reporting dashboard

Notification Types

Current required types:

Code Source Recipient
GENERAL Manual members
SUBSCRIPTION System member
REFERRAL System sender, receiver, chapter admin
SESSION System sender, receiver, chapter admin
BUSINESS_EXCHANGE System sender, receiver, chapter admin
EVENT System chapter-wise members
EVENT_ATTENDANCE System selected attended member
NEW_MEMBER_JOINED System other chapter members and chapter admins
GRIEVANCE System member
CHAPTER_ASSIGNED System member

Recommended Status Contract

Notification delivery status:

Value Meaning
PENDING notification row created, dispatch not attempted yet
SENT push dispatch attempted successfully
FAILED push dispatch failed
READ recipient opened/read notification

App preference status:

Value Meaning
ENABLED member wants this notification type
DISABLED member opted out for this notification type

App Settings Scope

Notification settings should be stored member-wise, not device-wise.

Reason:

  • a member expects the same toggle behavior across devices
  • module logic already works around member/member-chapter identities
  • device tokens should only decide delivery target, not business preference

Recommended rule:

  • preference is saved against member_id
  • notification recipients are still resolved chapter-wise where needed
  • delivery happens to all active devices of that member unless preference is disabled

Recommended Tables

1. notification_types

Master table for notification categories.

Suggested columns:

Column Notes
id UUID
code unique, e.g. REFERRAL
name display name
user_type MEMBER, CHAPTER_ADMIN, BOTH
can_disable bool
status ACTIVE, INACTIVE
created_at, updated_at, deleted_at standard

Why table instead of enum only:

  • app settings UI can be driven dynamically
  • display names can change without code-only dependency
  • future admin control is easier

2. member_notification_settings

Per-member preference table.

Suggested columns:

Column Notes
id UUID
member_id FK
notification_type_id FK
is_enabled bool
created_at, updated_at, deleted_at standard

Unique index:

member_id + notification_type_id

3. member_device_tokens

Stores app push tokens.

Suggested columns:

Column Notes
id UUID
member_id FK
device_token push token
platform ANDROID, IOS
device_name optional
app_version optional
is_active bool
last_used_at timestamp
created_at, updated_at, deleted_at standard

Unique index:

device_token

4. notifications

System notification definition row.

Suggested columns:

Column Notes
id UUID
notification_type_id FK
title title
message body text
image_path optional image
source_type model name, e.g. Referral, Event
source_id related source row id
created_by_user_id nullable
created_by_member_id nullable
metadata JSON payload
status PENDING, SENT, FAILED
sent_at nullable
created_at, updated_at, deleted_at standard

5. notification_recipients

Recipient rows for a notification.

Suggested columns:

Column Notes
id UUID
notification_id FK
member_id FK
member_chapter_id nullable, useful for chapter-context notifications
delivery_status PENDING, SENT, FAILED, READ
read_at nullable
delivered_at nullable
failure_reason nullable
created_at, updated_at, deleted_at standard

Unique index:

notification_id + member_id

This avoids duplicate delivery to the same member for the same notification.

Initial App Settings Keys

Your screenshot shows these toggles:

Key Notification Type Default
REFERRAL_RECEIVED REFERRAL enabled
ONE_TO_ONE_RECEIVED SESSION enabled
NEW_MEMBER_JOINED_CHAPTER NEW_MEMBER_JOINED enabled

Recommended Phase 1 rule:

  • keep settings dynamic in backend
  • UI can initially show only these three toggles
  • other notification types remain enabled by default until UI is expanded

Alternative:

  • expose all can-disable notification types immediately

Current safer recommendation:

  • backend supports all types
  • app settings UI starts with only the three toggles already designed

Recipient Resolution Rules

1. GENERAL

Source:

  • manual create from admin/app-admin flow

Inputs:

  • title
  • message
  • image
  • audience

Recommended audience contract:

Value Meaning
ALL_MEMBERS all approved members
CURRENT_CHAPTER_MEMBERS only members of a chapter

Required rule:

  • if audience is CURRENT_CHAPTER_MEMBERS, chapter_id is required

2. SUBSCRIPTION

Recipients:

  • the member whose chapter subscription is expiring, expired, or renewed

Events:

  • EXPIRING: chapter subscription expires within the configured warning window, currently 7 days
  • EXPIRED: chapter subscription expiry date is before the current server time
  • RENEWED: common notification service method exists, but automatic renewal trigger is pending until renewal storage/logic is added

Recommended source:

  • member_chapters.date_of_joining
  • current active chapter_fees.duration_value
  • current active chapter_fees.duration_unit

Current command:

php artisan notifications:send-subscription-status

Options:

  • --days=7 controls the expiring warning window.
  • --dry-run counts eligible rows without creating notifications.

Scheduler:

  • runs daily at 09:00 server time.

Duplicate rule:

  • the command creates at most one notification per member_chapter and subscription status (EXPIRING or EXPIRED).

3. REFERRAL

Recipients:

  • sender member
  • receiver member
  • chapter admins of the relevant chapter

Preference key:

  • receiver toggle should control receiver delivery
  • sender delivery can stay always enabled or configurable later

4. SESSION

Recipients:

  • session creator
  • session-with member
  • chapter admins of the relevant chapter

5. BUSINESS_EXCHANGE

Recipients:

  • referred by member
  • referred to member
  • chapter admins of the relevant chapter

Shared two-party push data for REFERRAL, SESSION, and BUSINESS_EXCHANGE:

  • sender_member_id: sender/from member id
  • receiver_member_id: receiver/to member id
  • referring_by_member_id: sender/from member id alias for referral-style screens
  • referring_to_member_id: receiver/to member id alias for referral-style screens

6. EVENT

Recipients:

  • chapter-wise members depending on visibility logic

Recommended mapping:

Event Visibility Recipients
ALL or app-wide equivalent all approved members
CHAPTER members of event chapter
INVITE_ONLY only explicitly assigned members if invite table exists, otherwise no push until invite logic exists

7. NEW_MEMBER_JOINED

Recipients:

  • other approved members of the joined chapter
  • chapter admins of the joined chapter

Exclusions:

  • the newly joined member
  • the creator/action taker, when that user is linked to a member

Current trigger points:

  • signup member approval from the admin portal
  • member creation from the admin portal
  • member creation from the app by a chapter admin
  • new chapter assignment for an already approved member

Important clarification:

A pure signup event has no chapter until chapter assignment exists, so this notification is sent only after the member has an assigned chapter and is approved.

Push data:

  • type: NEW_MEMBER_JOINED
  • source_id: notification source row id
  • member_id: newly joined member id

8. EVENT_ATTENDANCE

Recipients:

  • selected member whose attendance was marked

Exclusions:

  • the creator/action taker, when the creator is the same selected member

Current trigger point:

  • app chapter admin submits event attendance from POST /events/attendance/submit

Future trigger point:

  • admin portal attendance marking should call the same common event attendance notification service when portal-side attendance is added later

Important rule:

  • notification is created only when the member is newly marked present for that event; repeated submit for an already-present member should not create duplicate notifications

9. GRIEVANCE

Recipients:

  • the grievance creator member

Trigger:

  • when grievance status changes
  • optionally also when admin adds a resolution remark later

10. CHAPTER_ASSIGNED

Recipients:

  • member whose chapter row was newly added

Trigger:

  • only when a chapter is newly assigned
  • not when existing row is only updated

Delivery Preference Rule

Recipient resolution and preference filtering should be separated.

Flow:

  1. determine candidate recipients by business logic
  2. remove duplicates
  3. check member preference for that notification type
  4. create notification_recipients
  5. dispatch push to active device tokens

Special case:

  • mandatory notifications can bypass preference if required later

Phase 1 recommendation:

  • CHAPTER_ASSIGNED, GRIEVANCE, and SUBSCRIPTION should remain mandatory
  • user can disable only user-facing feed-style notifications such as referral/session/new-member-joined

Push Delivery Flow

Recommended service split:

NotificationService

Responsibilities:

  • create notification row
  • resolve recipients
  • insert recipient rows

NotificationPreferenceService

Responsibilities:

  • load member preference
  • decide if member can receive type

PushNotificationService

Responsibilities:

  • send to device tokens
  • mark delivery status
  • isolate FCM/APNS integration

NotificationTemplateService

Responsibilities:

  • generate title/message consistently from source models

Proposed App APIs

Base:

/api/app

1. App Settings - Notification Preferences

GET /settings/notifications
Authorization: Bearer {app_access_token}

Response:

{
  "message": "Notification settings found.",
  "data": [
    {
      "key": "REFERRAL_RECEIVED",
      "type": "REFERRAL",
      "label": "Referral Received",
      "is_enabled": true
    },
    {
      "key": "ONE_TO_ONE_RECEIVED",
      "type": "SESSION",
      "label": "One to One Received",
      "is_enabled": true
    },
    {
      "key": "NEW_MEMBER_JOINED_CHAPTER",
      "type": "NEW_MEMBER_JOINED",
      "label": "New Member Joined Chapter",
      "is_enabled": true
    }
  ]
}

2. Update Notification Preferences

POST /settings/notifications
Authorization: Bearer {app_access_token}

Request:

{
  "settings": [
    {
      "key": "REFERRAL_RECEIVED",
      "is_enabled": false
    },
    {
      "key": "ONE_TO_ONE_RECEIVED",
      "is_enabled": true
    }
  ]
}

3. Register Device Token

POST /notifications/device-token
Authorization: Bearer {app_access_token}

Request:

{
  "device_token": "push-token",
  "platform": "ANDROID",
  "device_name": "Samsung A54",
  "app_version": "1.0.0"
}

Behavior:

  • create or update device token row
  • mark active
  • attach to logged-in member

4. Notification Inbox

GET /notifications
Authorization: Bearer {app_access_token}

Suggested filters:

  • page
  • limit
  • is_read
  • type

5. Notification Detail / Read

GET /notifications/{notificationRecipient}
POST /notifications/{notificationRecipient}/read
POST /notifications/read-all

Proposed Admin APIs

Base:

/api/admin

1. Send General Notification

POST /notifications/general
Authorization: Bearer {admin_access_token}
Content-Type: multipart/form-data

Request:

{
  "title": "Monthly Meeting Reminder",
  "message": "Meeting starts at 6 PM.",
  "audience": "CURRENT_CHAPTER_MEMBERS",
  "chapter_id": "uuid"
}

With optional image upload.

2. Notification Logs

GET /notifications
Authorization: Bearer {admin_access_token}

Filters:

  • type
  • delivery_status
  • member_id
  • chapter_id
  • from_date
  • to_date

This is recommended for admin audit/debugging.

Trigger Matrix

Type Trigger Point Delivery Timing
GENERAL manual create API immediate
SUBSCRIPTION notifications:send-subscription-status scheduler daily
REFERRAL referral create immediate
SESSION session create/update immediate
BUSINESS_EXCHANGE business exchange create immediate
EVENT event create immediate
NEW_MEMBER_JOINED approved member joins a chapter immediate
EVENT_ATTENDANCE event attendance submitted by chapter admin immediate
GRIEVANCE grievance status update immediate
CHAPTER_ASSIGNED chapter added to member immediate

Suggested Message Pattern

Store final generated title/message in notifications.

Examples:

REFERRAL

  • title: New Referral
  • message: {sender_name} sent a referral to {receiver_name}

SESSION

  • title: One to One Session
  • message: {sender_name} scheduled a one to one session with {receiver_name}

BUSINESS_EXCHANGE

  • title: Business Exchange
  • message: {sender_name} recorded a business exchange of Rs. {amount}

EVENT

  • title: New Event
  • message: {event_name} has been created for {chapter_name}

NEW_MEMBER_JOINED

  • title: New Member Joined
  • message: {member_name} has joined {chapter_name}.

EVENT_ATTENDANCE

  • title: Event Attendance
  • message: Your attendance has been marked for {event_title}.

SUBSCRIPTION

  • title: Subscription Expiring
  • message: Your {chapter_name} subscription is expiring on {expiry_date}.
  • title: Subscription Expired
  • message: Your {chapter_name} subscription expired on {expiry_date}.
  • title: Subscription Renewed
  • message: Your {chapter_name} subscription has been renewed.

GRIEVANCE

  • title: Grievance Update
  • message: Your grievance status has been updated to {status}

CHAPTER_ASSIGNED

  • title: Chapter Assigned
  • message: You have been assigned to {chapter_name}

Delivery Ordering

Recommended order of work:

  1. device token registration
  2. notification type seed data
  3. member notification settings API
  4. notification inbox API
  5. admin general notification API
  6. system-triggered notification service
  7. scheduler for subscription expiry reminders

This order is safer because:

  • preferences need types
  • delivery needs device tokens
  • system triggers should use one common notification service

Required Clarifications Before Coding

These are the points that can create wrong behavior if assumed incorrectly:

  1. NEW_MEMBER_JOINED

    • confirm trigger should be chapter assignment, not bare signup
  2. SUBSCRIPTION

    • confirm exact trigger for subscribed
    • is it member approval, chapter assignment, payment success, or some future subscription table event
  3. EVENT

    • confirm exact recipient mapping by event visibility
    • especially for invite-only events
  4. App Settings

    • confirm whether Phase 1 UI should show only the 3 toggles in your screenshot
    • or all configurable notification types
  5. Admin/App source for GENERAL

    • your note says “from app”
    • confirm whether this means:
      • admin portal only
      • app-admin from mobile app
      • both

Recommended Build Decision

The safest implementation path is:

  1. build notification data model
  2. build app settings APIs
  3. build device token registration
  4. build notification inbox
  5. then connect module triggers one by one

That avoids hard-coding push logic inside referral/session/event controllers directly.