chitfund/docs/NOTIFICATION_API_FIX.md

5.9 KiB

🐛 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!):

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!):

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!):

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!):

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

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

ssh luckychit@192.168.8.148
cd /home/luckychit/apps/chitfund
./scripts/deploy.sh backend

Step 3: Verify Fix

# 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

{
  "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

{
  "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)

# Should return empty array with pagination
curl -H "Authorization: Bearer TOKEN" \
  https://chitfund.deepteklabs.com/api/notifications

Expected:

{
  "success": true,
  "data": {
    "notifications": [],
    "pagination": {
      "currentPage": 1,
      "totalPages": 0,
      "totalItems": 0,
      "itemsPerPage": 20
    }
  }
}

2. Test with Filters

# 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

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

// PostgreSQL → Use Sequelize methods
// MongoDB → Use Mongoose methods

2. Test Before Deploying

# 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.


  • 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! 🎉