Files
bakery-ia/docs/whatsapp/multi-tenant-implementation.md
2025-12-05 20:07:01 +01:00

12 KiB

Multi-Tenant WhatsApp Configuration - Implementation Summary

Overview

This implementation allows each bakery (tenant) to configure their own WhatsApp Business credentials in the settings UI, enabling them to send notifications to suppliers using their own WhatsApp Business phone number.

COMPLETED WORK

Phase 1: Backend - Tenant Service

1. Database Schema

File: services/tenant/app/models/tenant_settings.py

  • Added notification_settings JSON column to store WhatsApp and email configuration
  • Includes fields: whatsapp_enabled, whatsapp_phone_number_id, whatsapp_access_token, whatsapp_business_account_id, etc.

2. Pydantic Schemas

File: services/tenant/app/schemas/tenant_settings.py

  • Created NotificationSettings schema with validation
  • Added validators for required fields when WhatsApp is enabled

3. Service Layer

File: services/tenant/app/services/tenant_settings_service.py

  • Added "notification" category support
  • Mapped notification category to notification_settings column

4. Database Migration

File: services/tenant/migrations/versions/002_add_notification_settings.py

  • Created migration to add notification_settings column with default values
  • All existing tenants get default settings automatically

Phase 2: Backend - Notification Service

1. Tenant Service Client

File: shared/clients/tenant_client.py

  • Added get_notification_settings(tenant_id) method
  • Fetches notification settings via HTTP from Tenant Service

2. WhatsApp Business Service

File: services/notification/app/services/whatsapp_business_service.py

Changes:

  • Modified __init__ to accept tenant_client parameter
  • Renamed global config to global_access_token, global_phone_number_id, etc.
  • Added _get_whatsapp_credentials(tenant_id) method:
    • Fetches tenant notification settings
    • Checks if whatsapp_enabled is True
    • Returns tenant credentials if configured
    • Falls back to global config if not configured or incomplete
  • Updated send_message() to call _get_whatsapp_credentials() for each message
  • Modified _send_template_message() and _send_text_message() to accept credentials as parameters
  • Updated health_check() to use global credentials

3. WhatsApp Service Wrapper

File: services/notification/app/services/whatsapp_service.py

  • Modified __init__ to accept tenant_client parameter
  • Passes tenant_client to WhatsAppBusinessService

4. Service Initialization

File: services/notification/app/main.py

  • Added import for TenantServiceClient
  • Initialize TenantServiceClient in on_startup()
  • Pass tenant_client to WhatsAppService initialization

Phase 3: Frontend - TypeScript Types

1. Settings Types

File: frontend/src/api/types/settings.ts

  • Created NotificationSettings interface
  • Added to TenantSettings interface
  • Added to TenantSettingsUpdate interface
  • Added 'notification' to SettingsCategory type

Phase 4: Frontend - Component

1. Notification Settings Card

File: frontend/src/pages/app/database/ajustes/cards/NotificationSettingsCard.tsx

  • Complete UI component with sections for:
    • WhatsApp Configuration (credentials, API version, language)
    • Email Configuration (from address, name, reply-to)
    • Notification Preferences (PO, inventory, production, forecast alerts)
    • Channel selection (email/WhatsApp) for each notification type
  • Includes helpful setup instructions for WhatsApp Business
  • Responsive design with proper styling

Phase 5: Frontend - Translations

1. Spanish Translations

Files:

  • frontend/src/locales/es/ajustes.json - notification section added
  • frontend/src/locales/es/settings.json - "notifications" tab added

2. Basque Translations

Files:

  • frontend/src/locales/eu/ajustes.json - notification section added
  • frontend/src/locales/eu/settings.json - "notifications" tab added

Translation Keys Added:

  • notification.title
  • notification.whatsapp_config
  • notification.whatsapp_enabled
  • notification.whatsapp_phone_number_id (+ _help)
  • notification.whatsapp_access_token (+ _help)
  • notification.whatsapp_business_account_id (+ _help)
  • notification.whatsapp_api_version
  • notification.whatsapp_default_language
  • notification.whatsapp_setup_note/step1/step2/step3
  • notification.email_config
  • notification.email_enabled
  • notification.email_from_address/name/reply_to
  • notification.preferences
  • notification.enable_po_notifications/inventory_alerts/production_alerts/forecast_alert s
  • bakery.tabs.notifications

📋 REMAINING WORK

Frontend - BakerySettingsPage Integration

File: frontend/src/pages/app/settings/bakery/BakerySettingsPage.tsx

Changes needed (see FRONTEND_CHANGES_NEEDED.md for detailed instructions):

  1. Add Bell icon to imports
  2. Import NotificationSettings type
  3. Import NotificationSettingsCard component
  4. Add notificationSettings state variable
  5. Load notification settings in useEffect
  6. Add notifications tab trigger
  7. Add notifications tab content
  8. Update handleSaveOperationalSettings validation
  9. Add notification_settings to mutation
  10. Update handleDiscard function
  11. Update floating save button condition

Estimated time: 15 minutes

🔄 How It Works

Message Flow

  1. PO Event Triggered: When a purchase order is approved, an event is published to RabbitMQ
  2. Event Consumed: Notification service receives the event with tenant_id and supplier information
  3. Credentials Lookup:
    • WhatsAppBusinessService._get_whatsapp_credentials(tenant_id) is called
    • Fetches notification settings from Tenant Service via HTTP
    • Checks if whatsapp_enabled is True
    • If tenant has WhatsApp enabled AND credentials configured → uses tenant credentials
    • Otherwise → falls back to global environment variable credentials
  4. Message Sent: Uses resolved credentials to send message via Meta WhatsApp API
  5. Logging: Logs which credentials were used (tenant-specific or global)

Configuration Levels

Global (Fallback):

  • Environment variables: WHATSAPP_ACCESS_TOKEN, WHATSAPP_PHONE_NUMBER_ID, etc.
  • Used when tenant settings are not configured or WhatsApp is disabled
  • Configured at deployment time

Per-Tenant (Primary):

  • Stored in tenant_settings.notification_settings JSON column
  • Configured through UI in Bakery Settings → Notifications tab
  • Each tenant can have their own WhatsApp Business credentials
  • Takes precedence over global config when enabled and configured

Backward Compatibility

Existing code continues to work without changes PO event consumer already passes tenant_id - no changes needed Falls back gracefully to global config if tenant settings not configured Migration adds default settings to existing tenants automatically

📊 Testing Checklist

Backend Testing

  • Run tenant service migration: cd services/tenant && alembic upgrade head
  • Verify notification_settings column exists in tenant_settings table
  • Test API endpoint: GET /api/v1/tenants/{tenant_id}/settings/notification
  • Test API endpoint: PUT /api/v1/tenants/{tenant_id}/settings/notification
  • Verify notification service starts successfully with tenant_client
  • Send test WhatsApp message with tenant credentials
  • Send test WhatsApp message without tenant credentials (fallback)
  • Check logs for "Using tenant-specific WhatsApp credentials" message
  • Check logs for "Using global WhatsApp credentials" message

Frontend Testing

  • Apply BakerySettingsPage changes
  • Navigate to Settings → Bakery Settings
  • Verify "Notifications" tab appears
  • Click Notifications tab
  • Verify NotificationSettingsCard renders correctly
  • Toggle "Enable WhatsApp" checkbox
  • Verify credential fields appear/disappear
  • Fill in WhatsApp credentials
  • Verify helper text appears correctly
  • Verify setup instructions appear
  • Toggle notification preferences
  • Verify channel checkboxes (Email/WhatsApp)
  • WhatsApp channel checkbox should be disabled when WhatsApp not enabled
  • Click Save button
  • Verify success toast appears
  • Refresh page and verify settings persist
  • Test in both Spanish and Basque languages

Integration Testing

  • Configure tenant WhatsApp credentials via UI
  • Create a purchase order for a supplier with phone number
  • Approve the purchase order
  • Verify WhatsApp message is sent using tenant credentials
  • Check logs confirm tenant credentials were used
  • Disable tenant WhatsApp in UI
  • Approve another purchase order
  • Verify message uses global credentials (fallback)
  • Re-enable tenant WhatsApp
  • Remove credentials (leave fields empty)
  • Verify fallback to global credentials

🔒 Security Considerations

Current Implementation

  • Credentials stored in database (PostgreSQL JSONB)
  • Access controlled by tenant isolation
  • Only admin/owner roles can modify settings
  • HTTPS required for API communication
  • Password input type for access token field
  • Implement field-level encryption for whatsapp_access_token
  • Add audit logging for credential changes
  • Implement credential rotation mechanism
  • Add "Test Connection" button to verify credentials
  • Rate limiting on settings updates
  • Alert on failed message sends

📚 Documentation

Existing Documentation

  • services/notification/WHATSAPP_SETUP_GUIDE.md - WhatsApp Business setup guide
  • services/notification/WHATSAPP_TEMPLATE_EXAMPLE.md - Template creation guide
  • services/notification/WHATSAPP_QUICK_REFERENCE.md - Quick reference
  • services/notification/MULTI_TENANT_WHATSAPP_IMPLEMENTATION.md - Implementation details

Documentation Updates Needed

  • Update WHATSAPP_SETUP_GUIDE.md with per-tenant configuration instructions
  • Add screenshots of UI settings page
  • Document fallback behavior
  • Add troubleshooting section for tenant-specific credentials
  • Update API documentation with new tenant settings endpoint

🚀 Deployment Steps

1. Backend Deployment

# 1. Deploy tenant service changes
cd services/tenant
alembic upgrade head
kubectl apply -f kubernetes/tenant-deployment.yaml

# 2. Deploy notification service changes
cd services/notification
kubectl apply -f kubernetes/notification-deployment.yaml

# 3. Verify services are running
kubectl get pods -n bakery-ia
kubectl logs -f deployment/tenant-service -n bakery-ia
kubectl logs -f deployment/notification-service -n bakery-ia

2. Frontend Deployment

# 1. Apply BakerySettingsPage changes (see FRONTEND_CHANGES_NEEDED.md)
# 2. Build frontend
cd frontend
npm run build

# 3. Deploy
kubectl apply -f kubernetes/frontend-deployment.yaml

3. Verification

# Check database
psql -d tenant_db -c "SELECT tenant_id, notification_settings->>'whatsapp_enabled' FROM tenant_settings;"

# Check logs
kubectl logs -f deployment/notification-service -n bakery-ia | grep -i whatsapp

# Test message send
curl -X POST http://localhost:8000/api/v1/test-whatsapp \
  -H "Content-Type: application/json" \
  -d '{"tenant_id": "xxx", "phone": "+34612345678"}'

📞 Support

For questions or issues:

  • Check logs: kubectl logs deployment/notification-service -n bakery-ia
  • Review documentation in services/notification/
  • Verify credentials in Meta Business Suite
  • Test with global credentials first, then tenant credentials

Success Criteria

Implementation is complete when:

  • Backend can fetch tenant notification settings
  • Backend uses tenant credentials when configured
  • Backend falls back to global credentials when needed
  • UI displays notification settings tab
  • Users can configure WhatsApp credentials
  • Settings save and persist correctly
  • Messages sent using tenant-specific credentials
  • Logs confirm credential selection
  • All translations work in Spanish and Basque
  • Backward compatibility maintained

Implementation Status: 95% Complete (Frontend integration remaining) Last Updated: 2025-11-13