> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Report Scheduling Guide

> Encore Health OS's report scheduling system automates report generation and delivery. Schedule reports to run daily, weekly, monthly, or on custom schedules, w…

## Overview

Encore Health OS's report scheduling system automates report generation and delivery. Schedule reports to run daily, weekly, monthly, or on custom schedules, with automatic email delivery to recipients.

## Features

### Schedule Types

* **Daily**: Run at specified time every day
* **Weekly**: Run on specific day of week
* **Monthly**: Run on specific day of month
* **Custom**: Define custom cron expression

### Output Formats

* **PDF**: Professional formatted reports (requires additional library)
* **CSV**: Spreadsheet-compatible data export
* **Excel**: Native .xlsx format (requires additional library)

### Delivery Options

* Email to multiple recipients
* Include summary section
* Timezone-aware scheduling
* Retry on failure

## Usage

### Creating a Schedule

```typescript theme={null}
import { useReportSchedules } from '@/platform/reports/hooks/useReportSchedules';

function ReportScheduling() {
  const { createSchedule } = useReportSchedules(organizationId);

  const handleCreate = () => {
    createSchedule.mutate({
      report_id: reportId,
      organization_id: organizationId,
      name: 'Monthly Financial Summary',
      schedule_type: 'monthly',
      day_of_month: 1,
      run_time: '08:00:00',
      timezone: 'America/New_York',
      output_format: 'pdf',
      recipients: [
        { email: 'cfo@example.com', name: 'Jane Doe' },
        { email: 'controller@example.com', name: 'John Smith' },
      ],
      enabled: true,
    });
  };
}
```

### Schedule Management Page

```typescript theme={null}
import { ReportSchedulesPage } from '@/platform/reports/pages/ReportSchedulesPage';

// Add to router
<Route path="/reports/schedules" element={<ReportSchedulesPage />} />
```

### Schedule Form Component

```typescript theme={null}
import { ReportScheduleForm } from '@/platform/reports/components/ReportScheduleForm';

<ReportScheduleForm
  onSubmit={handleSubmit}
  defaultValues={schedule}
  isSubmitting={isSubmitting}
/>
```

## Schedule Configuration

### Time Settings

* **Run Time**: 24-hour format (HH:MM:SS)
* **Timezone**: IANA timezone identifier
* **Next Run**: Automatically calculated by trigger

### Recipients

Add multiple recipients with:

* Email address (required)
* Display name (optional)

Example:

```json theme={null}
[
  {"email": "user@example.com", "name": "John Doe"},
  {"email": "manager@example.com", "name": "Jane Smith"}
]
```

### State Tracking

System automatically tracks:

* `next_run_at` - Next execution time
* `last_run_at` - Last execution time
* `last_run_status` - success | partial | failed
* `last_run_error` - Error message if failed
* `run_count` - Total executions

## Cron Expressions

### Presets

* Daily at 8am: `0 8 * * *`
* Weekly Monday 8am: `0 8 * * 1`
* Monthly 1st 8am: `0 8 1 * *`
* Monthly 15th 8am: `0 8 15 * *`

### Custom Cron Format

```
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * *
```

Examples:

* Every weekday 9am: `0 9 * * 1-5`
* Every 6 hours: `0 */6 * * *`
* Last day of month: `0 8 L * *` (custom schedule type)

## Execution Flow

### Automated Execution

1. Edge function runs every 15 minutes
2. Queries schedules where `next_run_at <= now()`
3. Executes report SQL with parameters
4. Generates output in requested format
5. Sends email to all recipients
6. Updates schedule status and calculates next run

### Manual Execution

Trigger immediate execution:

```typescript theme={null}
const { data } = await supabase.functions.invoke('execute-scheduled-reports', {
  body: { scheduleId: 'specific-schedule-id' }
});
```

## Error Handling

### Retry Logic

* Failed executions: Automatic retry (3 attempts)
* Exponential backoff: 5min, 15min, 1hr
* Permanent failure after 3 attempts
* Error message logged in `last_run_error`

### Failure Notifications

When a report fails to generate, the first recipient automatically receives a branded failure notification email with:

* Error message and details (sanitized to prevent sensitive information exposure)
* Troubleshooting suggestions
* Link to reports page

**⚠️ Security Note:** Error details in failure emails are sanitized before rendering. Never include raw database errors, stack traces, or internal paths in user-facing error messages. Use generic, user-friendly error descriptions.

### Recovery

Failed schedules:

1. Review error in `last_run_error`
2. Fix underlying issue (report SQL, permissions)
3. Enable schedule again
4. Next run calculated automatically

## Email Delivery

### Branded Email Templates

Scheduled reports use professional HTML email templates featuring:

* Branded Encore Health OS header with gradient
* Report details card with name and description
* Statistics row (generated date, row count, format, file size)
* Prominent download button with 7-day signed URL
* Next scheduled run indicator
* Mobile-responsive design

### Email Template Localization

Email templates support multiple languages:

* Templates use translation keys via `locale` parameter
* Default: English (`en`)
* Infrastructure ready for Spanish (`es`), French (`fr`), and more
* Per-organization locale settings planned for future releases

### Customizing Email Content

The `include_summary` flag adds a columns preview to the email:

```typescript theme={null}
{
  include_summary: true,
  // Email will show: "Columns: name, amount, date, +5 more"
}
```

### Pre-Rendered HTML Support

For advanced customization, the email system supports pre-rendered HTML:

```typescript theme={null}
await supabase.functions.invoke('send-email-notification', {
  body: {
    notificationId,
    recipientEmail: 'user@example.com',
    subject: 'Custom Report',
    html: customHtmlContent,
    skipTemplate: true,
  },
});
```

## Best Practices

### Performance

* Limit report data (use date ranges)
* Add indexes on frequently queried columns
* Test report SQL independently first
* Monitor execution time in logs

### Scheduling

* Avoid peak hours for heavy reports
* Stagger multiple reports (avoid all at same time)
* Consider timezone of recipients
* Use off-hours for resource-intensive reports

### Recipients

* Use distribution lists for large teams
* Keep recipient list under 50 people
* Include only stakeholders who need the report
* Update email addresses regularly

### Output Format

* CSV: Best for data analysis (Excel, Google Sheets)
* PDF: Best for presentations and archived records
* Excel: Best for formatted spreadsheets with formulas

## Monitoring

### Schedule Health

Check schedule status:

* `enabled = true` and `next_run_at` populated
* `last_run_status = 'success'`
* No recent `last_run_error`
* `run_count` incrementing

### Edge Function Logs

Monitor execution:

```
supabase functions logs execute-scheduled-reports
```

Look for:

* Schedules processed
* Execution errors
* Email delivery failures

### Delivery Confirmation

Recipients should confirm receipt of:

* First scheduled report
* Changed reports (after modifications)
* Critical financial reports

## Troubleshooting

### Schedule Not Running

1. Check `enabled = true`
2. Verify `next_run_at` is in the past
3. Review edge function logs
4. Confirm organization has access to report

### Report Fails to Generate

1. Test report SQL independently
2. Check report parameters are valid
3. Verify user has permissions
4. Review RLS policies on data tables

### Email Not Delivered

1. Check recipient email addresses
2. Verify Entra/Gmail provider configuration and required secrets
3. Review email delivery logs
4. Check spam folders
5. Confirm sender identity/domain is properly configured in the selected provider

### Incorrect Schedule Time

1. Verify timezone setting
2. Check cron expression format
3. Ensure run\_time is valid (HH:MM:SS)
4. Review calculated next\_run\_at

## Advanced Features

### Conditional Scheduling

Schedule based on data conditions:

```sql theme={null}
-- Only run if data exists
SELECT * FROM fa_transactions
WHERE transaction_date >= current_date - interval '1 month'
AND EXISTS (SELECT 1 FROM fa_transactions LIMIT 1)
```

### Parameterized Reports

Pass dynamic parameters:

```typescript theme={null}
{
  report_id: reportId,
  parameters: {
    start_date: '2025-01-01',
    end_date: '2025-01-31',
    fund_id: 'specific-fund-uuid'
  }
}
```

### Multi-Format Delivery

Create multiple schedules for same report:

* PDF to executives
* CSV to analysts
* Excel to department heads

## Related Documentation

* [Reporting Engine](./reporting-guide.md)
* [Email Notifications](./email-notifications-guide.md)
* [Report Visualizations](./report-visualizations-guide.md)
