chitfund/backend/WHATSAPP_USAGE_EXAMPLES.md

17 KiB

WhatsApp Integration & Payment Reminders - Usage Guide

🚀 Quick Start

1. Install Dependencies

cd backend
npm install

This installs:

  • node-cron@^3.0.3 - Scheduled reminders
  • moment-timezone@^0.5.43 - Date/time handling

2. Start Server

npm run dev

You should see:

⏰ Starting payment reminder scheduler...
Payment reminder scheduler started (9:00 AM IST daily)
🚀 Server running on port 3000
📱 WhatsApp share: http://localhost:3000/api/share
🔔 Notifications: http://localhost:3000/api/notifications

📱 How to Use WhatsApp Sharing

Example 1: Share Payment Receipt (After Payment)

Scenario: Member just made a payment, wants to share receipt

Backend:

// In your payment controller, after recording payment
const payment = await Payment.create({...});

// Send notification to member
const WhatsAppHelper = require('../utils/whatsapp-helper');
const message = WhatsAppHelper.generatePaymentReceipt(
  payment,
  group,
  member
);

await Notification.create({
  type: 'payment_confirmation',
  user_id: member.id,
  group_id: group.id,
  payment_id: payment.id,
  channel: 'whatsapp',
  message: message,
  status: 'sent'
});

Flutter:

// In payment success dialog
import '../../core/utils/whatsapp_util.dart';
import '../../shared/widgets/payment_success_dialog.dart';

// After payment recorded
PaymentSuccessDialog.show(
  context,
  paymentId: payment.id,
  amount: 5000,
  groupName: 'Family Chit Fund',
  transactionId: 'TXN123456',
  paymentDate: DateTime.now(),
  paymentMethod: 'UPI',
);

// Or manually trigger share
await WhatsAppUtil.sharePaymentReceipt(paymentId);

Example 2: Share Draw Result (After Draw Completion)

Scenario: Manager completed a draw, wants to announce winner

Backend:

// After draw completion
const draw = await MonthlyDraw.create({...});

// Generate share link
const message = WhatsAppHelper.generateDrawResult(
  group,
  winner,
  prizeAmount,
  month,
  totalMembers
);

const whatsappUrl = WhatsAppHelper.generateShareLink(
  winner.mobile_number,
  message
);

// Send to winner
await Notification.create({
  type: 'draw_result',
  user_id: winner.id,
  group_id: group.id,
  draw_id: draw.id,
  channel: 'whatsapp',
  message: message,
  status: 'sent'
});

Flutter:

// In draw results screen
import '../../core/utils/whatsapp_util.dart';
import '../../shared/widgets/whatsapp_share_button.dart';

// After draw completion
WhatsAppShareButton(
  label: 'Share Results',
  onPressed: () async {
    await WhatsAppUtil.shareDrawResult(draw.id);
  },
)

// Or open share options sheet
WhatsAppShareSheet.show(
  context,
  [
    WhatsAppShareOption(
      title: 'Share with Winner',
      icon: Icons.emoji_events,
      color: Colors.green.shade600,
      onTap: () => WhatsAppUtil.shareDrawResult(draw.id),
    ),
    WhatsAppShareOption(
      title: 'Share with All Members',
      icon: Icons.group,
      color: Colors.blue.shade600,
      onTap: () => shareWithAllMembers(),
    ),
  ],
);

Example 3: Invite New Member

Scenario: Manager wants to invite someone to join group

Backend API Call:

POST /api/share/group-invite
Authorization: Bearer <manager-token>

{
  "groupId": "group-uuid",
  "recipientPhone": "9876543210"
}

Flutter:

// In group details page or add member dialog
TextFormField(
  controller: phoneController,
  decoration: InputDecoration(labelText: 'Phone Number'),
)

WhatsAppShareButton(
  label: 'Send Invitation',
  onPressed: () async {
    await WhatsAppUtil.shareGroupInvite(
      groupId,
      phoneController.text,
    );
  },
)

Example 4: Manual Payment Reminder

Scenario: Manager wants to remind specific member

Flutter:

// In member list, add action button
IconButton(
  icon: Icon(Icons.whatsapp, color: Color(0xFF25D366)),
  onPressed: () async {
    await WhatsAppUtil.sendPaymentReminder(groupId, memberId);
  },
  tooltip: 'Send WhatsApp Reminder',
)

Example 5: Bulk Reminders

Scenario: Manager wants to remind all unpaid members

Flutter:

// In group details page
ElevatedButton.icon(
  icon: Icon(Icons.send_rounded),
  label: Text('Send Reminders to All'),
  onPressed: () async {
    final result = await WhatsAppUtil.sendBulkReminders(groupId);
    
    if (result != null) {
      final count = result['total_reminders'];
      showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: Text('$count Reminders Generated'),
          content: Text('Open WhatsApp for each member?'),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: Text('Later'),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
                // Open each WhatsApp link
                // (User will need to manually send each)
              },
              child: Text('Yes, Open'),
            ),
          ],
        ),
      );
    }
  },
)

Payment Reminder Schedule

Automatic Reminders:

The system automatically sends reminders at:

Days Before/After Due Type Urgency
7 days before Upcoming payment Low
3 days before Payment due soon Medium
1 day before Payment due tomorrow ⚠️ High
0 (On due date) Payment due today ⚠️ High
1 day overdue Payment overdue 🚨 Urgent
3 days overdue Still overdue 🚨 Urgent
7 days overdue Seriously overdue 🚨 Critical
14 days overdue Very seriously overdue 🚨 Critical
30 days overdue Final reminder 🚨 Critical

Reminder Logic:

For each active group:
  Calculate current month
  Calculate due date (start_date + months + draw_date)
  Get days until due
  
  If (days until due) in [7, 3, 1, 0]:
    For each member who hasn't paid:
      Create reminder notification
      Log in database
  
  If overdue (days < 0):
    If days overdue in [1, 3, 7, 14, 30]:
      For each member who hasn't paid:
        Create URGENT reminder
        Log in database

📊 Notification Types

  • payment_reminder - Regular reminder (7, 3, 1, 0 days before)
  • payment_overdue - Overdue payment (1, 3, 7, 14, 30 days after)
  • payment_confirmation - Payment received successfully
  • draw_result - Draw completed, winner announced
  • member_joined - New member added to group
  • member_removed - Member removed from group
  • welcome_message - Welcome new member
  • group_invite - Invitation to join group
  • group_started - Group moved from forming to active
  • group_completed - Group completed all months

System:

  • manager_notification - Important manager notifications
  • system_alert - Critical system alerts

🧪 Testing Guide

Test 1: Manual Reminder Trigger

# Create test script: backend/test-reminders.js

const ReminderService = require('./src/services/reminder-service');

(async () => {
  console.log('Testing manual reminders...');
  const result = await ReminderService.triggerManualReminders();
  console.log(`Sent ${result} reminders`);
  process.exit(0);
})();

# Run it:
node test-reminders.js

Test 2: Share Payment Receipt

curl -X POST http://localhost:3000/api/share/payment-receipt \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"paymentId": "your-payment-id"}'

Test 3: Get Notifications

curl -X GET http://localhost:3000/api/notifications \
  -H "Authorization: Bearer YOUR_TOKEN"

Test 4: Get Unread Count

curl -X GET http://localhost:3000/api/notifications/unread-count \
  -H "Authorization: Bearer YOUR_TOKEN"

📱 Flutter Integration Examples

Add to Payment Recording Dialog

// After payment is recorded successfully

final payment = await recordPayment(...);

if (payment != null) {
  // Show success dialog with WhatsApp share
  await PaymentSuccessDialog.show(
    context,
    paymentId: payment.id,
    amount: payment.amount,
    groupName: group.name,
    transactionId: payment.transactionId,
    paymentDate: payment.paymentDate,
    paymentMethod: payment.paymentMethod,
  );
}

Add to Draw Results Screen

// After draw completion

WhatsAppShareButton(
  label: 'Share Results on WhatsApp',
  onPressed: () async {
    await WhatsAppUtil.shareDrawResult(draw.id);
  },
)

Add to Member List (Manager)

// In member card actions
Row(
  children: [
    WhatsAppIconButton(
      onPressed: () async {
        await WhatsAppUtil.sendPaymentReminder(
          groupId,
          member.id,
        );
      },
      tooltip: 'Send Reminder',
    ),
    // Other actions...
  ],
)

Add Notifications to Bottom Nav

BottomNavigationBar(
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: 'Home',
    ),
    BottomNavigationBarItem(
      icon: Obx(() => NotificationBadge(
        count: NotificationService.to.unreadCount.value,
        child: Icon(Icons.notifications),
      )),
      label: 'Notifications',
    ),
    // Other items...
  ],
  onTap: (index) {
    if (index == 1) {
      Get.to(() => NotificationCenterPage());
    }
  },
)

🔔 Notification Center Features

Features Implemented:

  • List all notifications
  • Show unread count badge
  • Mark as read on tap
  • Mark all as read
  • Swipe to delete
  • Pull to refresh
  • Infinite scroll pagination
  • Filter by type/status
  • Empty state when no notifications
  • Skeleton loader while loading

Usage:

// Navigate to notification center
Get.to(() => NotificationCenterPage());

// Check unread count
final count = NotificationService.to.unreadCount.value;

// Refresh notifications
await NotificationService.to.refresh();

// Mark all as read
await NotificationService.to.markAllAsRead();

🎯 Common Use Cases

Use Case 1: New Member Joins

// In add member success callback
await Notification.create({
  type: 'member_joined',
  user_id: managerId,
  group_id: groupId,
  channel: 'in_app',
  message: '${memberName} joined ${groupName}',
});

// Optionally send welcome WhatsApp to new member
final welcomeMsg = WhatsAppHelper.generateWelcomeMessage(
  member,
  group,
  manager
);
await openWhatsApp(member.phone, welcomeMsg);

Use Case 2: Manager Wants Quick Reminder

// Add quick action in group details
QuickActionCard(
  title: 'Send Payment Reminders',
  subtitle: 'Remind unpaid members',
  icon: Icons.send,
  color: Colors.orange.shade600,
  onTap: () async {
    final result = await WhatsAppUtil.sendBulkReminders(groupId);
    
    if (result != null) {
      final count = result['total_reminders'];
      SnackbarUtil.showSuccess('$count reminders generated!');
    }
  },
)

Use Case 3: Member Views Notifications

// Member dashboard - show recent notifications
Obx(() {
  final recentNotifications = NotificationService.to
      .notifications
      .take(3)
      .toList();
      
  return Column(
    children: recentNotifications.map((n) =>
      ListTile(
        leading: Icon(n.getIcon(), color: n.getColor()),
        title: Text(n.title),
        subtitle: Text(n.message, maxLines: 1),
        trailing: Text(n.getTimeAgo()),
        onTap: () => Get.to(() => NotificationCenterPage()),
      )
    ).toList(),
  );
})

🔧 Scheduler Configuration

Current Schedule:

  • Time: 9:00 AM IST daily
  • Timezone: Asia/Kolkata
  • Cron: '0 9 * * *'

Customize Schedule:

// In reminder-service.js

// Run every hour
cron.schedule('0 * * * *', async () => { ... });

// Run twice daily (9 AM and 6 PM)
cron.schedule('0 9,18 * * *', async () => { ... });

// Run every Monday at 9 AM
cron.schedule('0 9 * * 1', async () => { ... });

// Multiple schedules
cron.schedule('0 9 * * *', () => sendMorningReminders());
cron.schedule('0 18 * * *', () => sendEveningReminders());

📊 Monitoring & Analytics

Get Reminder Statistics:

const stats = await ReminderService.getReminderStats(groupId, 30);

console.log(stats);
// {
//   total: 150,
//   sent: 145,
//   failed: 5,
//   success_rate: "96.67"
// }

Get Upcoming Reminders (Preview):

const upcoming = await ReminderService.getUpcomingReminders(groupId);

console.log(upcoming);
// {
//   group_name: "Family Chit Fund",
//   current_month: 5,
//   due_date: "08 Nov 2025",
//   days_until_due: 3,
//   unpaid_members: 8,
//   unpaid_member_list: [...]
// }

🎨 Message Customization

Customize WhatsApp Messages:

Edit backend/src/utils/whatsapp-helper.js:

// Example: Add company branding
static generatePaymentReceipt(payment, group, member) {
  return `🎉 *Payment Successful!*\n\n` +
         `👤 Name: ${member.full_name}\n` +
         `🏦 Group: ${group.name}\n` +
         `💰 Amount: ${this.formatCurrency(payment.amount)}\n` +
         // ... more details ...
         `\n\n` +
         `✅ Payment recorded successfully!\n` +
         `Thank you for your trust! 🙏\n\n` +
         `_Your Company Name_\n` +  // Customize this
         `_Website: yourwebsite.com_\n` + // Add your link
         `_Support: +91-XXXXXXXXXX_`; // Add support number
}

// Example: Add regional language support
static generatePaymentReminderHindi(member, group, ...) {
  return `⏰ *भुगतान अनुस्मारक*\n\n` +
         `प्रिय ${member.full_name},\n\n` +
         `आपकी मासिक किस्त ${daysLeft} दिनों में देय है।\n\n` +
         // ... rest in Hindi
}

🔐 Security Considerations

Rate Limiting:

// Prevent spam
const rateLimit = require('express-rate-limit');

const shareLimit = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 10, // Max 10 shares per 15 minutes
  message: 'Too many share requests'
});

router.post('/payment-receipt', shareLimit, auth, async (req, res) => {
  // ...
});

Validation:

// Validate phone numbers
const validatePhone = (phone) => {
  const cleaned = phone.replace(/\D/g, '');
  return /^[0-9]{10}$/.test(cleaned);
};

// Validate ownership
if (payment.user_id !== req.user.id && req.user.role !== 'manager') {
  return res.status(403).json({ message: 'Not authorized' });
}

💡 Best Practices

1. Always Log Notifications

// Every WhatsApp action should create a notification record
await Notification.create({
  type: 'payment_reminder',
  user_id: memberId,
  group_id: groupId,
  channel: 'whatsapp',
  message: message,
  status: 'sent'
});

2. Handle Errors Gracefully

try {
  await WhatsAppUtil.shareReceipt(paymentId);
} catch (e) {
  SnackbarUtil.showError('Could not open WhatsApp. Please try again.');
}

3. Provide Feedback

// Show loading
SnackbarUtil.showLoading('Generating receipt...');

// Dismiss on complete
SnackbarUtil.dismiss();
SnackbarUtil.showSuccess('Opening WhatsApp...');

4. Respect User Preferences

// Check if user wants WhatsApp notifications
if (user.preferences?.whatsapp_enabled) {
  await sendWhatsAppReminder();
}

🚀 Production Checklist

Before going live:

  • Test all WhatsApp share functions
  • Verify scheduler runs at correct time
  • Test reminder logic with various scenarios
  • Check timezone handling (IST)
  • Test with actual WhatsApp on mobile
  • Verify phone number formatting
  • Test bulk operations
  • Monitor server logs
  • Set up error alerts
  • Test on multiple devices
  • Verify database performance
  • Add rate limiting
  • Implement retry logic for failed sends
  • Set up monitoring dashboard

📞 Support & Troubleshooting

WhatsApp not opening?

  • Check if WhatsApp is installed on device
  • Verify phone number format (10 digits)
  • Test URL in browser first
  • Check console for errors

Reminders not sending?

  • Check server logs for cron execution
  • Verify timezone settings
  • Check database for notification records
  • Test manual trigger: ReminderService.triggerManualReminders()

Notifications not showing?

  • Check API endpoint responses
  • Verify NotificationService is initialized
  • Check network connectivity
  • Look for errors in Flutter console

🎉 You're Ready!

All WhatsApp integration and payment reminder features are now implemented!

Next: Test the features, customize messages, and deploy to production! 🚀