chitfund/docs/NOTIFICATION_API_FIX.md

289 lines
5.9 KiB
Markdown

# 🐛 Notification API 500 Error - Fixed
## Issue
**Error**: 500 Internal Server Error
**Endpoint**: `GET /api/notifications?page=1&limit=20`
**URL**: https://chitfund.deepteklabs.com/api/notifications
---
## Root Cause
The notifications route was using **Mongoose** (MongoDB) methods like:
- `.find()`
- `.countDocuments()`
- `.populate()`
- `.aggregate()`
But your Notification model is using **Sequelize** (PostgreSQL). This mismatch caused the 500 error.
---
## What Was Fixed
### File: `backend/src/routes/notifications.js`
#### 1. GET /api/notifications Route
**Before** (Mongoose - Wrong!):
```javascript
const notifications = await Notification.find(query)
.sort({ createdAt: -1 })
.limit(parseInt(limit))
.skip((parseInt(page) - 1) * parseInt(limit))
.populate('group_id', 'name');
const total = await Notification.countDocuments(query);
```
**After** (Sequelize - Correct!):
```javascript
const { count, rows: notifications } = await Notification.findAndCountAll({
where,
order: [['created_at', 'DESC']],
limit: parseInt(limit),
offset: offset,
include: [
{
model: ChitGroup,
as: 'group',
attributes: ['name'],
required: false
}
]
});
```
#### 2. GET /api/notifications/stats Route
**Before** (Mongoose - Wrong!):
```javascript
const total = await Notification.countDocuments({ user_id: req.user.id });
const byType = await Notification.aggregate([
{ $match: { user_id: req.user.id } },
{ $group: { _id: '$type', count: { $sum: 1 } } }
]);
```
**After** (Sequelize - Correct!):
```javascript
const total = await Notification.count({
where: { user_id: req.user.id }
});
const byType = await Notification.findAll({
attributes: [
'type',
[Sequelize.fn('COUNT', Sequelize.col('type')), 'count']
],
where: { user_id: req.user.id },
group: ['type'],
raw: true
});
```
---
## Mongoose vs Sequelize Method Comparison
| Operation | Mongoose (MongoDB) | Sequelize (PostgreSQL) |
|-----------|-------------------|------------------------|
| **Find with filter** | `.find(query)` | `.findAll({ where })` |
| **Count** | `.countDocuments(query)` | `.count({ where })` |
| **Sort** | `.sort({ field: -1 })` | `order: [['field', 'DESC']]` |
| **Limit** | `.limit(10)` | `limit: 10` |
| **Skip/Offset** | `.skip(20)` | `offset: 20` |
| **Populate/Join** | `.populate('field', 'name')` | `include: [{ model, as, attributes }]` |
| **Aggregate** | `.aggregate([...])` | `attributes: [Sequelize.fn(...)]` |
| **Find and count** | N/A | `.findAndCountAll({ ... })` |
---
## How to Deploy
### Step 1: Commit Changes
```bash
git add backend/src/routes/notifications.js
git commit -m "Fix notification API - use Sequelize instead of Mongoose"
git push origin prodnew
```
### Step 2: Deploy to Production
```bash
ssh luckychit@192.168.8.148
cd /home/luckychit/apps/chitfund
./scripts/deploy.sh backend
```
### Step 3: Verify Fix
```bash
# Test the API
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://chitfund.deepteklabs.com/api/notifications?page=1&limit=20
# Should return:
{
"success": true,
"data": {
"notifications": [...],
"pagination": {...}
}
}
```
---
## Expected Response Format
### GET /api/notifications
```json
{
"success": true,
"data": {
"notifications": [
{
"id": "uuid",
"type": "payment_reminder",
"user_id": "uuid",
"group_id": "uuid",
"title": "Payment Reminder",
"message": "Your payment is due...",
"status": "sent",
"priority": "high",
"created_at": "2025-11-06T...",
"read_at": null,
"group": {
"name": "Group A"
}
}
],
"pagination": {
"currentPage": 1,
"totalPages": 1,
"totalItems": 0,
"itemsPerPage": 20
}
}
}
```
### GET /api/notifications/stats
```json
{
"success": true,
"data": {
"total": 10,
"unread": 5,
"read": 5,
"by_type": [
{
"type": "payment_reminder",
"count": "3"
},
{
"type": "draw_result",
"count": "2"
}
]
}
}
```
---
## Testing
### 1. Test Empty Response (No Notifications)
```bash
# Should return empty array with pagination
curl -H "Authorization: Bearer TOKEN" \
https://chitfund.deepteklabs.com/api/notifications
```
**Expected**:
```json
{
"success": true,
"data": {
"notifications": [],
"pagination": {
"currentPage": 1,
"totalPages": 0,
"totalItems": 0,
"itemsPerPage": 20
}
}
}
```
### 2. Test with Filters
```bash
# Filter by type
curl -H "Authorization: Bearer TOKEN" \
"https://chitfund.deepteklabs.com/api/notifications?type=payment_reminder"
# Filter by status
curl -H "Authorization: Bearer TOKEN" \
"https://chitfund.deepteklabs.com/api/notifications?status=sent"
```
### 3. Test Stats Endpoint
```bash
curl -H "Authorization: Bearer TOKEN" \
https://chitfund.deepteklabs.com/api/notifications/stats
```
---
## Why This Happened
This is a common issue when:
1. Copying code from a MongoDB project to a PostgreSQL project
2. Using boilerplate code without adapting it
3. Not testing API endpoints before deployment
---
## Prevention
### 1. Always Check Database Type
```javascript
// PostgreSQL → Use Sequelize methods
// MongoDB → Use Mongoose methods
```
### 2. Test Before Deploying
```bash
# Test locally first
npm start
curl http://localhost:3000/api/notifications
```
### 3. Use Consistent Patterns
All your other models use Sequelize correctly. This was an isolated issue in the notifications route.
---
## Related Files
- `backend/src/routes/notifications.js` ✅ Fixed
- `backend/src/models/Notification.js` ✅ Already correct (Sequelize)
- `backend/src/models/index.js` ✅ Associations defined correctly
---
## Summary
**Problem**: Route used Mongoose methods with Sequelize model
**Solution**: Converted to proper Sequelize syntax
**Status**: ✅ Fixed
**Deploy**: `./scripts/deploy.sh backend`
---
**The notification API should now work correctly!** 🎉