# Subscriber Status System ## Overview The newsletter system tracks subscribers with a `status` field that determines whether they receive newsletters. ## Status Field ### Database Schema ```javascript { _id: ObjectId("..."), email: "user@example.com", subscribed_at: ISODate("2025-11-11T15:50:29.478Z"), status: "active" // or "inactive" } ``` ### Status Values | Status | Description | Receives Newsletters | |--------|-------------|---------------------| | `active` | Subscribed and active | ✅ Yes | | `inactive` | Unsubscribed | ❌ No | ## How It Works ### Subscription Flow ``` User subscribes ↓ POST /api/subscribe ↓ Create subscriber with status: 'active' ↓ User receives newsletters ``` ### Unsubscription Flow ``` User unsubscribes ↓ POST /api/unsubscribe ↓ Update subscriber status: 'inactive' ↓ User stops receiving newsletters ``` ### Re-subscription Flow ``` Previously unsubscribed user subscribes again ↓ POST /api/subscribe ↓ Update status: 'active' + new subscribed_at date ↓ User receives newsletters again ``` ## API Endpoints ### Subscribe ```bash curl -X POST http://localhost:5001/api/subscribe \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com"}' ``` **Creates subscriber with:** - `email`: user@example.com - `status`: "active" - `subscribed_at`: current timestamp ### Unsubscribe ```bash curl -X POST http://localhost:5001/api/unsubscribe \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com"}' ``` **Updates subscriber:** - `status`: "inactive" ## Newsletter Sending ### Who Receives Newsletters Only subscribers with `status: 'active'` receive newsletters. **Sender Service Query:** ```python subscribers_collection.find({'status': 'active'}) ``` **Admin API Query:** ```python subscribers_collection.count_documents({'status': 'active'}) ``` ### Testing ```bash # Check active subscriber count curl http://localhost:5001/api/admin/stats | jq '.subscribers' # Output: # { # "total": 10, # "active": 8 # } ``` ## Database Operations ### Add Active Subscriber ```javascript db.subscribers.insertOne({ email: "user@example.com", subscribed_at: new Date(), status: "active" }) ``` ### Deactivate Subscriber ```javascript db.subscribers.updateOne( { email: "user@example.com" }, { $set: { status: "inactive" } } ) ``` ### Reactivate Subscriber ```javascript db.subscribers.updateOne( { email: "user@example.com" }, { $set: { status: "active", subscribed_at: new Date() }} ) ``` ### Query Active Subscribers ```javascript db.subscribers.find({ status: "active" }) ``` ### Count Active Subscribers ```javascript db.subscribers.countDocuments({ status: "active" }) ``` ## Common Issues ### Issue: Stats show 0 active subscribers but subscribers exist **Cause:** Old bug where stats checked `{active: true}` instead of `{status: 'active'}` **Solution:** Fixed in latest version. Stats now correctly query `{status: 'active'}` **Verify:** ```bash # Check database directly docker-compose exec mongodb mongosh munich_news -u admin -p changeme \ --authenticationDatabase admin \ --eval "db.subscribers.find({status: 'active'}).count()" # Check via API curl http://localhost:5001/api/admin/stats | jq '.subscribers.active' ``` ### Issue: Newsletter not sending to subscribers **Possible causes:** 1. Subscribers have `status: 'inactive'` 2. No subscribers in database 3. Email configuration issue **Debug:** ```bash # Check subscriber status docker-compose exec mongodb mongosh munich_news -u admin -p changeme \ --authenticationDatabase admin \ --eval "db.subscribers.find().pretty()" # Check active count curl http://localhost:5001/api/admin/stats | jq '.subscribers' # Try sending curl -X POST http://localhost:5001/api/admin/send-newsletter \ -H "Content-Type: application/json" ``` ## Migration Notes ### If you have old subscribers without status field Run this migration: ```javascript // Set all subscribers without status to 'active' db.subscribers.updateMany( { status: { $exists: false } }, { $set: { status: "active" } } ) ``` ### If you have subscribers with `active: true/false` field Run this migration: ```javascript // Convert old 'active' field to 'status' field db.subscribers.updateMany( { active: true }, { $set: { status: "active" }, $unset: { active: "" } } ) db.subscribers.updateMany( { active: false }, { $set: { status: "inactive" }, $unset: { active: "" } } ) ``` ## Best Practices ### 1. Always Check Status When querying subscribers for sending: ```python # ✅ Correct subscribers_collection.find({'status': 'active'}) # ❌ Wrong subscribers_collection.find({}) # Includes inactive ``` ### 2. Soft Delete Never delete subscribers - just set status to 'inactive': ```python # ✅ Correct - preserves history subscribers_collection.update_one( {'email': email}, {'$set': {'status': 'inactive'}} ) # ❌ Wrong - loses data subscribers_collection.delete_one({'email': email}) ``` ### 3. Track Subscription History Consider adding fields: ```javascript { email: "user@example.com", status: "active", subscribed_at: ISODate("2025-01-01"), unsubscribed_at: null, // Set when status changes to inactive resubscribed_count: 0 // Increment on re-subscription } ``` ### 4. Validate Before Sending ```python # Check subscriber count before sending count = subscribers_collection.count_documents({'status': 'active'}) if count == 0: return {'error': 'No active subscribers'} ``` ## Related Documentation - [ADMIN_API.md](ADMIN_API.md) - Admin API endpoints - [DATABASE_SCHEMA.md](DATABASE_SCHEMA.md) - Complete database schema - [NEWSLETTER_API_UPDATE.md](../NEWSLETTER_API_UPDATE.md) - Newsletter API changes