Unified email reports

This commit is contained in:
Frank John Begornia
2026-01-02 01:19:07 +08:00
parent 2e1ad5526c
commit d0d82aa8e1
229 changed files with 7374 additions and 812 deletions

467
README.md Normal file
View File

@@ -0,0 +1,467 @@
# Email Reports - Dockerized Container
Unified Docker container for automated daily order email reports for **both Crew Sportswear and MerchBay**.
## Overview
This container runs cron jobs daily at **23:55 CT** to:
1. Query orders from both Crew and MerchBay databases
2. Generate separate CSV reports for each brand
3. Email reports to recipients via SMTP
**Cron Schedule:**
- **23:55** - Crew Sportswear report
- **23:56** - MerchBay report
## Quick Start
### 1. Create `.env` file
```bash
cp .env.example .env
vim .env
```
Configure your environment variables:
```env
# Crew Database
DB_HOST_CREW=mysql
DB_NAME_CREW=custom_design
DB_USER_CREW=crew_user
DB_PASS_CREW=your_password
# MerchBay Database
DB_HOST_MERCHBAY=mysql
DB_NAME_MERCHBAY=merchbay_laravel
DB_USER_MERCHBAY=merchbay_user
DB_PASS_MERCHBAY=your_password
# SMTP
SMTP_PASS_CREW=crew_gmail_app_password
SMTP_PASS_MERCHBAY=merchbay_gmail_app_password
```
### 2. Build and Run
```bash
# Build image
docker-compose build
# Start container
docker-compose up -d
# Check logs
docker logs -f email_reports_crew
```
### 3. Test Manually
```bash
# Test Crew report
docker exec email_reports_unified BRAND=crew php /app/send_report.php
# Test MerchBay report
docker exec email_reports_unified BRAND=merchbay php /app/send_report.php
# Check cron log
docker exec email_reports_unified tail -f /var/log/cron.log
# Check email log (shows both brands)
docker exec email_reports_unified tail -f /app/email.log
```
┌──────────────────────────────────────────┐
│ Email Reports Container (Unified) │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Cron Jobs: │ │
│ │ 23:55 → BRAND=crew │ │
│ │ 23:56 → BRAND=merchbay │ │
│ │ │ │
│ │ send_report.php │ │
│ │ └─ PHPMailer │ │
│ └────────────────────────────────────┘ │
│ │ │
└─────────────┼────────────────────────────┘
├──> MySQL: custom_design (Crew)
├──> MySQL: merchbay_laravel (MerchBay)
└──> SMTP: Gmail (2 accounts)
├──────> MySQL (crew-app-net)
└──────> SMTP (smtp.gmail.com)
```
## Fsend_report.php** - Unified report generator (handles both brands)
- **index.php** - Legacy Crew report (kept for backward compatibility)
- **dbconfig.php** - Database connection (env-aware)
- **phpmailer/** - Email library
## Cron Schedule
```cron
55 23 * * * BRAND=crew php /app/send_report.php >> /var/log/cron.log 2>&1
56 23 * * * BRAND=merchbay php /app/send_report.php >> /var/log/cron.log 2>&1
```
**23:55 CT** - Crew Sportswear
**23:56 CT** - MerchBay
Both run daily, 1 minute apart.
55 23 * * * cd /app && php index.php >> /var/log/cron.log 2>&1
```
Runs daily at **11:55 PM Central Time**
## Environment Variables
### Crew Sportswear
| Variable | Default | Description |
|----------|---------|-------------|
| DB_HOST_CREW | mysql | MySQL host for Crew |
| DB_PORT_CREW | 3306 | MySQL port |
| DB_NAME_CREW | custom_design | Crew database name |
| DB_USER_CREW | crew_user | Crew database username |
| DB_PASS_CREW | - | Crew database password |
| SMTP_PASS_CREW | - | Gmail app password for mail@crewsportswear.com |
### MerchBay
| Variable | Default | Description |
|----------|---------|-------------|
| DB_HOST_MERCHBAY | mysql | MySQL host for MerchBay |
| DB_PORT_MERCHBAY | 3306 | MySQL port |
| DB_NAME_MERCHBAY | merchbay_laravel | MerchBay database name |
| DB_USER_MERCHBAY | merchbay_user | MerchBay database username |
| DB_PASS_MERCHBAY | - | MerchBay database password |
| SMTP_PASS_MERCHBAY | - | Gmail app password for support@merchbay.com |
### Shared
| Variable | Default | Description |
|----------|---------|-------------|
| SMTP_HOST | smtp.gmail.com | SMTP server |
| SMTP_PORT | 587 | SMTP port |
## Brand Configuration
The unified container handles both brands using the `BRAND` environment variable:
**Crew Sportswear (`BRAND=crew`)**:
- Database: `custom_design`
- From: `orders@crewsportswear.com`
- To: `graphics@crewsportswear.com`
- BCC: webmaster, angelo, production @crewsportswear.com
- Admin: https://admin.crewsportswear.app
- CSV: `daily_order_reports_crew/`
**MerchBay (`BRAND=merchbay`)**:
- Database: `merchbay_laravel`
- From: `orders@merchbay.com`
- To: `graphics@crewsportswear.com`
- BCC: webmaster, production @crewsportswear.com
- Admin: https://merchbay.app
- CSV: `daily_order_reports_merchbay/`
## Networks
Container must be on **crew-app-net** to access MySQL:
```yaml
networks:
- crew-app-net
networks:
crew-app-net:
external: true
```
Create network if it doesn't exist:
```bash
docker network create crew-app-net
```
## Volumes
```yaml
volumes:
- ./daily_order_reports_crew:/app/daily_order_reports_crew # Crew CSV archives
- ./daily_order_reports_merchbay:/app/daily_order_reports_merchbay # MerchBay CSV archives
- ./email.log:/app/email.log # Combined execution log
```
Both brands write to the same `email.log` with prefixes `[CREW]` and `[MERCHBAY]`.
## Deployment
### Automated Deployment (Gitea Actions)
**Production deployment** is automated via Gitea Actions when pushing to `main` or `master` branch.
```bash
# Trigger deployment
git add .
git commit -m "Update email reports"
git push origin main
```
The workflow will:
1. Build Docker image
2. Transfer to production server via SSH
3. Deploy to `/var/www/apps/email_reports`
4. Start container with cron
5. Verify container is running
**Registry build** is triggered by version tags:
```bash
# Create version tag
git tag v1.0.0
git push origin v1.0.0
```
This builds and pushes to your Docker registry.
### Manual Deployment
```bash
# Deploy via docker-compose
docker-compose up -d --build
# Or build specific image version
docker build -t email-reports:1.0.0 .
docker tag email-reports:1.0.0 your-registry/email-reports:1.0.0
docker push your-registry/email-reports:1.0.0
```
### Required Gitea Secrets
Configure in your repository settings:
- `DEPLOY_SSH_KEY` - SSH private key for deployment server
- `DEPLOY_HOST` - Deployment server hostname/IP
- `DEPLOY_USER` - SSH username
- `REGISTRY_URL` - Docker registry URL (for version tags)
- `REGISTRY_USER` - Registry username
- `REGISTRY_PASSWORD` - Registry password
### Server Setup (First Time)
On your production server, create the deployment directory and `.env` file:
```bash
# Create directory
sudo mkdir -p /var/www/apps/email_reports
sudo chown $USER:$USER /var/www/apps/email_reports
cd /var/www/apps/email_reports
# Create .env file
cat > .env << 'EOL'
DB_HOST=mysql
DB_PORT=3306
DB_NAME=custom_design
DB_USER=crew_user
DB_PASS=your_secure_password
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=mail@crewsportswear.com
SMTP_PASS=your_gmail_app_password
EMAIL_TO=graphics@crewsportswear.com
EMAIL_BCC=webmaster@crewsportswear.com,angelo@crewsportswear.com,production@crewsportswear.com
APP_URL=https://www.crewsportswear.com
ADMIN_URL=https://admin.crewsportswear.app
EOL
chmod 600 .env
# Create data directories
mkdir -p daily_order_reports
touch email.log
chmod 666 email.log
# Ensure network exists
docker network create crew-app-net || true
```
Now push to trigger the first deployment!
### Multiple Instances
For MerchBay, create similar setup in `email_reports_merchbay/`:
```yaml
# docker-compose.yml in email_reports_merchbay/
services:
email-reports-merchbay:
build: .
container_name: email_reports_merchbay
environment:
- DB_NAME=merchbay_db
- EMAIL_TO=orders@merchbay.com
# ... other env vars
```
## Monitoring
### Check Container Health
```bash
# Container status
docker ps | grep email_reports
# Should show email_reports_unified
# Health check
docker inspect email_reports_unified | grep -A 5 Health
```
### View Logs
```bash
# Real-time cron logs (both brands)
docker exec email_reports_unified tail -f /var/log/cron.log
# Email execution logs (prefixed by brand)
docker exec email_reports_unified tail -f /app/email.log
# Example log output:
# 2026-01-02 23:55:00 [CREW] successfully sent (5 orders)
# 2026-01-02 23:56:00 [MERCHBAY] No order for today
# Last 50 lines
docker logs --tail 50 email_reports_unified
# Filter by brand
docker exec email_reports_unified grep "\[CREW\]" /app/email.log | tail -10
docker exec email_reports_unified grep "\[MERCHBAY\]" /app/email.log | tail -10
```
### Verify Cron Schedule
```bash
# View active crontab (should show both jobs)
docker exec email_reports_unified crontab -l
# Expected:
# 55 23 * * * BRAND=crew php /app/send_report.php >> /var/log/cron.log 2>&1
# 56 23 * * * BRAND=merchbay php /app/send_report.php >> /var/log/cron.log 2>&1
# Check if cron is running
docker exec email_reports_unified ps aux | grep crond
```
## Troubleshooting
### Database Connection Failed
```bash
# Test MySQL connectivity
docker exec email_reports_crew ping mysql
# Test database connection
docker exec email_reports_crew php -r "new PDO('mysql:host=mysql;dbname=custom_design', 'user', 'pass');"
# Check network
docker network inspect crew-app-net
```
### Email Not Sending
```bash
# Enable debug mode
docker exec email_reports_crew sed -i 's|// \$mail->SMTPDebug|\$mail->SMTPDebug|' /app/index.php
# Run manually with debug
docker exec email_reports_crew php /app/index.php
# Check SMTP credentials in .env
```
### Cron Not Running
```bash
# Check cron daemon
docker exec email_reports_crew ps aux | grep crond
# Restart container
docker restart email_reports_crew
# View crontab
docker exec email_reports_crew cat /etc/crontabs/root
```
### Wrong Timezone
```bash
# Verify timezone
docker exec email_reports_crew date
docker exec email_reports_crew cat /etc/timezone
# Should show: America/Chicago
```
### Permissions Issues
```bash
# Fix CSV directory permissions
docker exec email_reports_crew chmod 755 /app/daily_order_reports
# Fix log file
docker exec email_reports_crew chmod 666 /app/email.log
```
## Maintenance
### Update Cron Schedule
Edit Dockerfile and rebuild:
```dockerfile
RUN echo "30 22 * * * cd /app && php index.php" > /etc/crontabs/root
```
### Rotate Logs
```bash
# Manually clear logs (optional)
docker exec email_reports_crew truncate -s 0 /var/log/cron.log
docker exec email_reports_crew truncate -s 0 /app/email.log
```
### Backup Reports
```bash
# Archive old CSV files
tar -czf daily_reports_backup_$(date +%Y%m%d).tar.gz daily_order_reports/
# Or sync to S3/backup location
```
## Security
1. **Never commit `.env`** - Use `.env.example` only
2. **Use Gmail App Passwords** - Not your main password
3. **Restrict network access** - Only join necessary networks
4. **Rotate credentials** - Change passwords regularly
5. **Monitor logs** - Check for unauthorized access
## Advantages of Separate Container
**Isolation** - Reports run independently of web apps
**Reusability** - Can serve multiple apps (Crew + MerchBay)
**Simple Deployment** - Single purpose, easy to update
**Resource Control** - Limit CPU/memory for cron jobs
**Independent Scaling** - Restart without affecting web traffic
**Clean Separation** - No coupling with Laravel/framework
## Next Steps
1. Test database connectivity
2. Verify SMTP credentials
3. Run manual test: `docker exec email_reports_crew php /app/index.php`
4. Wait for 23:55 or adjust cron for testing
5. Monitor logs for first automated run
6. Set up similar container for MerchBay reports