Email workspaceReport generation completed contract
Purpose/audience: $report->user, the requesting user.
Implementation: App\Mail\ReportGenerated. Baseline view: resources/views/emails/management-reports/generation-completed.blade.php. Usage evidence: app/Jobs/CFOAIReport/NotifyUserReportCompleted.php:57. These are static references, not proof of current production delivery.
Suggested subject: Report Generation Completed. HTML title alone does not set the mail header.
Suggested preheader: Your requested report is ready. The PDF is attached.
Portable placeholder contract
| Token | Existing source / derivation | Requirement |
|---|---|---|
| {{logo_url}} | Existing Built app_name PNG | Optional deployment override; the concrete project HTTPS PNG is the default. Approved HTTPS or matching CID only. |
| {{preheader}} | Suggested text above, assembled only from already available values | Required escaped text; not a new backend record or processing guarantee. |
| {{first_name}} | $report->user->first_name | Required escaped name of the report requester. |
| {{business_name}} | $report->business_name | Required escaped report business identity. |
| {{report_name}} | $report->name | Required escaped report title; preserve long values. |
| {{period_from}} | $report->from->format('d-m-Y') | Required formatted source date; no inferred timezone or altered reporting period. |
| {{period_to}} | $report->to->format('d-m-Y') | Required formatted source date; no invented expiry or completion time. |
| {{report_url}} | $url = 'https://cfoai.built.africa/reports/' + $report->uuid | Required complete existing CFO AI report URL; this is an external destination relative to the main app, not an attachment-download endpoint. |
Content, states and integration decisions
- Preserve requester name, report business/title, both formatted dates and the instruction that the PDF is attached. The same generated report can also be viewed on the CFO AI dashboard.
- The action explicitly says View report and the email explains that it opens Built CFO AI. The added fallback repeats that same URL. No separate download URL, processing-time promise or approval claim is invented.
- ReportGenerated implements ShouldQueue and is queued by NotifyUserReportCompleted. Keep the existing CFO AI From name, PDF generation, attachment naming, caller behavior and subject. The preview attaches nothing and is not proof of a runtime PDF.
- States: standard and long first/business/report names plus long fictional link. Dates retain the current d-m-Y display; do not infer a timezone or change the reporting range.
Portable HTML/text and safe handling
ready/report-completed.html and ready/report-completed.txt provide the portable extracts. Every populated state has matching .html and .txt files under previews/. All sample links are local design explanations; no real invitation, report or account action is executed. Placeholder {{names}} are not automatically Laravel Blade syntax. Convert each mapping explicitly using existing data and server-side URL generation; retain all required values and do not insert untrusted raw HTML.
Escape text and attribute values. Validate any application/CFO AI URL separately against approved HTTPS hosts before escaping it; preserve complete generated links and encrypted/signed parameters. Use the provided concrete public PNG or an approved HTTPS/CID override. There are no hidden optional content sections to populate here; required identities/counts should not be silently omitted. Unsupported data has not been invented.
All drafts use the approved compact transactional shell with 16px body text, a minimal Built footer and native light/dark CSS. Email-client rendering and blocked-image behavior remain separate tests. See integration-notes.html for shared provider/image limitations, and easy-wins-batch.md for the whole batch. No production template, sender, transport or application behavior is changed.