# Weekly Email Report

> Email version of the Slack weekly report

**Created:** Jan 20, 2026
**Status:** Plan Ready
**Effort:** 2-4 hours
**Ongoing Cost:** ~$5/mo (SendGrid free tier may cover it)

---

## Problem

Weekly insights currently go to Slack only. Some stakeholders:
- Don't use Slack regularly
- Want reports in their inbox
- Need to forward to others
- Want PDF attachment for records

---

## Solution

Email version of the existing weekly report with rich HTML formatting.

### Report Sections

Same as Slack report:
1. **Week Summary** - Calls, conversions, pipeline value
2. **Top Performers** - Leaderboard
3. **What's Working** - Winning patterns
4. **Needs Attention** - Stalled deals, overdue callbacks
5. **Next Week Focus** - AI recommendations

### Email Format

```html
<!DOCTYPE html>
<html>
<head>
  <style>
    /* Mobile-responsive styles */
    .container { max-width: 600px; margin: 0 auto; }
    .stat-card { background: #f8f9fa; padding: 16px; border-radius: 8px; }
    .winner { color: #059669; }
    .warning { color: #d97706; }
  </style>
</head>
<body>
  <div class="container">
    <h1>RateRight Weekly Report</h1>
    <p>Week of Jan 13-19, 2026</p>

    <div class="stat-card">
      <h2>Week Summary</h2>
      <p><strong>194</strong> calls made (+12% vs last week)</p>
      <p><strong>8</strong> conversions ($24,500 value)</p>
      <p><strong>4.1%</strong> conversion rate</p>
    </div>

    <h2>Top Performers</h2>
    <ol>
      <li><strong>Tony</strong> - 87 calls, 4 conversions</li>
      <li><strong>Angelica</strong> - 62 calls, 3 conversions</li>
    </ol>

    <h2>What's Working</h2>
    <ul>
      <li>Formworkers converting at 6.2% (vs 4.1% average)</li>
      <li>Calls between 2-4pm have highest connect rate</li>
    </ul>

    <h2>Needs Attention</h2>
    <ul class="warning">
      <li>12 hot leads haven't been contacted in 48+ hours</li>
      <li>5 callbacks overdue</li>
    </ul>

    <h2>Focus for Next Week</h2>
    <p>Push on the 12 hot leads early Monday. Best time: 9-11am.</p>

    <hr>
    <p style="color: #6b7280; font-size: 12px;">
      RateRight Growth Engine | <a href="https://app.rateright.com.au">Open Dashboard</a>
    </p>
  </div>
</body>
</html>
```

---

## Database Schema

```sql
CREATE TABLE IF NOT EXISTS email_subscriptions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email VARCHAR(255) NOT NULL,
  name VARCHAR(100),
  report_type VARCHAR(50) NOT NULL, -- 'weekly', 'daily', 'monthly'
  is_active BOOLEAN DEFAULT TRUE,
  user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  unsubscribed_at TIMESTAMPTZ,
  UNIQUE(email, report_type)
);

CREATE TABLE IF NOT EXISTS email_logs (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  subscription_id UUID REFERENCES email_subscriptions(id),
  report_type VARCHAR(50),
  sent_at TIMESTAMPTZ DEFAULT NOW(),
  status VARCHAR(20), -- 'sent', 'failed', 'bounced'
  sendgrid_id VARCHAR(100),
  error_message TEXT
);
```

---

## SendGrid Integration

```javascript
// src/services/emailReports.js
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

async function sendWeeklyReport() {
  // Get report data (reuse from weeklyReport.js)
  const reportData = await generateWeeklyReportData();

  // Render HTML
  const html = renderWeeklyReportEmail(reportData);

  // Get subscribers
  const subscribers = await supabase
    .from('email_subscriptions')
    .select('*')
    .eq('report_type', 'weekly')
    .eq('is_active', true);

  // Send to each subscriber
  for (const sub of subscribers.data) {
    try {
      await sgMail.send({
        to: sub.email,
        from: 'reports@rateright.com.au',
        subject: `RateRight Weekly Report - ${formatDate(new Date())}`,
        html: html,
        trackingSettings: {
          clickTracking: { enable: true },
          openTracking: { enable: true }
        }
      });

      await logEmailSent(sub.id, 'sent');
    } catch (err) {
      await logEmailSent(sub.id, 'failed', err.message);
    }
  }
}
```

---

## API Endpoints

```
GET  /api/reports/email/subscriptions      # List subscriptions
POST /api/reports/email/subscribe          # Subscribe email
DELETE /api/reports/email/unsubscribe      # Unsubscribe
POST /api/reports/email/test               # Send test email
GET  /api/reports/email/logs               # Email send logs
```

---

## Scheduling

```javascript
// In src/jobs/index.js
// Run after Slack report (Monday 7:15am AEST)
cron.schedule('15 7 * * 1', async () => {
  await sendWeeklyReport();
}, { timezone: 'Australia/Sydney' });
```

---

## UI Components

### EmailSubscriptionsSettings.jsx
- Manage email subscriptions
- Add external stakeholders
- Toggle active/inactive
- Send test email

Location: More → Settings → Email Reports

---

## Implementation Steps

### Phase 1: SendGrid Setup (0.5 hours)
1. [ ] Create SendGrid account (free tier: 100 emails/day)
2. [ ] Verify sender domain
3. [ ] Get API key, add to Railway

### Phase 2: Backend (1.5 hours)
1. [ ] Create migration
2. [ ] Create email service
3. [ ] Create HTML template
4. [ ] Create API endpoints

### Phase 3: Integration (0.5 hours)
1. [ ] Reuse weekly report data generation
2. [ ] Add to Monday cron schedule
3. [ ] Add error handling/retry

### Phase 4: Frontend (1 hour)
1. [ ] Create EmailSubscriptionsSettings
2. [ ] Add to Settings page
3. [ ] Test email button

---

## Environment Variables

```
SENDGRID_API_KEY=SG.xxxxx
EMAIL_FROM=reports@rateright.com.au
```

---

## Email Template Variants

### 1. Full Report (Default)
All sections, detailed stats

### 2. Executive Summary
Just the key numbers, 3 bullet points

### 3. Manager View
Includes individual rep breakdowns

---

## Unsubscribe Handling

Every email includes unsubscribe link:
```
https://app.rateright.com.au/unsubscribe?token=xxx&email=xxx
```

Token is signed JWT to prevent unauthorized unsubscribes.

---

## Success Metrics

- 90% email delivery rate
- Open rate >50%
- Click-through to dashboard >20%
- Zero spam complaints
