289 lines
5.9 KiB
Markdown
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!** 🎉
|
|
|