291 lines
5.7 KiB
Markdown
291 lines
5.7 KiB
Markdown
# 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
|