Files
calvana/temp_files/v4/fix_tabs.py
Omair Saleh c52c97df17 Automations engine: multi-channel messaging + dashboard
THE STAR OF THE SHOW — the automation engine is now visible.

## New: Unified Messaging Layer (src/lib/messaging.ts)
Channel waterfall: WhatsApp → SMS → Email
- sendToDonor() routes to best available channel
- Respects donor consent flags (whatsappOptIn, emailOptIn)
- Falls back automatically if primary channel fails
- Every attempt logged to AnalyticsEvent for dashboard

## New: Email Integration (src/lib/email.ts)
Bring-your-own-key: charity pastes their Resend or SendGrid API key
- Resend: free 3,000 emails/month
- SendGrid: free 100/day
- Messages come from THEIR domain (donations@mymosque.org)
- Plain text auto-converted to clean HTML

## New: SMS Integration (src/lib/sms.ts)
Bring-your-own-key: charity pastes their Twilio credentials
- Pay-as-you-go (~3p per SMS)
- UK number normalization (07xxx → +447xxx)
- Reaches donors without WhatsApp or email

## New: /dashboard/automations — the visible engine
A. Dark hero stats: Messages this week per channel + delivery rate
B. Live channels: WhatsApp/Email/SMS with status, features, stats
C. The Pipeline: visual 4-step automation sequence
   - What triggers, what's sent, which channels, waterfall explanation
D. Scheduled reminders: upcoming messages with timing
E. Message feed: recent messages with channel icon, status, time

## New: /api/messaging/status — dashboard data endpoint
Returns channels, stats (7 day), history (50 recent), pending reminders

## New: /api/messaging/test — send test message to admin

## Schema: 8 new Organization columns
emailProvider, emailApiKey, emailFromAddress, emailFromName
smsProvider, smsAccountSid, smsAuthToken, smsFromNumber

## Settings: 2 new channel rows in the checklist
- Email: provider selector (Resend/SendGrid) + API key + from address
- SMS: Twilio credentials + from number
Both follow the same checklist expand/collapse pattern

## Nav: Automations added between Money and Reports
Home → Collect → Money → Automations → Reports → Settings

## Stats tracking
Messages logged as AnalyticsEvent:
  message.whatsapp.receipt.sent
  message.email.reminder_1.failed
  message.sms.reminder_2.sent
Donor PII masked in logs (last 4 digits of phone, email obfuscated)
2026-03-04 23:20:50 +08:00

31 lines
1.2 KiB
Python

#!/usr/bin/env python3
import os
BASE = '/home/forge/app.charityright.org.uk'
pages = {
'app/Filament/Resources/CustomerResource/Pages/ListCustomers.php': 'all',
'app/Filament/Resources/DonationResource/Pages/ListDonations.php': 'today',
'app/Filament/Resources/AppealResource/Pages/ListAppeals.php': 'live',
'app/Filament/Resources/ApprovalQueueResource/Pages/ListApprovalQueues.php': 'pending',
'app/Filament/Resources/ScheduledGivingDonationResource/Pages/ListScheduledGivingDonations.php': 'active',
}
for rel_path, default_tab in pages.items():
path = os.path.join(BASE, rel_path)
with open(path, 'r') as f:
c = f.read()
if 'getDefaultActiveTab' not in c:
method = "\n public function getDefaultActiveTab(): string | int | null\n {\n return '" + default_tab + "';\n }\n"
last_brace = c.rstrip().rfind('}')
c = c[:last_brace] + method + '}\n'
with open(path, 'w') as f:
f.write(c)
print('Added default tab "' + default_tab + '" to ' + os.path.basename(path))
else:
print('Already has default tab: ' + os.path.basename(path))
print('Done')