17 KiB
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 remindersmoment-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 Related:
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 Related:
draw_result- Draw completed, winner announced
Member Related:
member_joined- New member added to groupmember_removed- Member removed from groupwelcome_message- Welcome new member
Group Related:
group_invite- Invitation to join groupgroup_started- Group moved from forming to activegroup_completed- Group completed all months
System:
manager_notification- Important manager notificationssystem_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! 🚀