BuiltEmail workspace

Employee payslip contract

Implementation: App\Mail\payslip. Baseline view: resources/views/emails/payroll/payslip.blade.php, using mail::message. Referenced callers: app/Http/Controllers/General/emailsController.php:444 (sendpayslip) and :463 (sendpayslips). PDF selection: app/Payrun.php:981, PayslipView(). Static references establish usage evidence, not production delivery.

Suggested subject: payslip for {{pay_period}} (existing exact lowercase pattern).

Suggested preheader: Your {{pay_period}} payslip from {{business_name}}. The PDF contains the details.

Placeholder contract

TokenExisting source / derivationHandling
{{logo_url}}Original Built app_name PNGOptional deployment override. Concrete approved HTTPS logo is already present; use approved absolute HTTPS or a matching attached CID.
{{preheader}}Suggested text above, using existing period/businessRequired escaped text; not a new payment or delivery guarantee.
{{first_name}}$payslip->employee->first_nameRequired escaped employee identity; not the business owner or payroll operator.
{{pay_period}}date('F, Y', strtotime($payrun->run_date))Required existing formatted period. Also used in the original subject and PDF filename. Preserve formatting/timezone semantics; do not turn it into payday or a deadline.
{{net_salary}}$business->currency->symbol . number_format($payslip->net_salary, 2) in the body viewRequired formatted existing amount. Preserve currency prefix, two-decimal formatting, zero/negative values. Do not recompute deductions or use FX/base salary fields.
{{business_name}}$data['business']->name, loaded from $payrun->business_idRequired escaped sign-off identity. This is not automatically payroll_settings.Company_name or the local employee-business object used later in build().
{{portal_url}}Existing literal https://payroll.built.africa/Conditional trusted HTTPS payroll-site root. Bind the same value to button and fallback when employee.email is truthy; otherwise remove the whole marked portal block and text counterpart. Do not change to /login, a document URL or a reset/setup endpoint.

Source-only condition: $payslip->employee->email controls the portal section; it is not printed as a new email field. Source-only sender name: $data['payroll_settings']->Company_name from payrun-business payroll settings. These values remain in the existing Mailable/header contract; they are not invented required body tokens.

Recipients, headers, queue and attachments

States and conditional portal section

States: Ghana, Namibia, Kenya, default PDF mapping, zero net salary, long values, and no employee email. Country states share one email body and differ only in existing source data/attachment selection; they are not three new email types.

The standalone HTML includes a complete marked portal block. In Blade wrap it in the original employee.email predicate. When false, remove the button, its explanatory text and visible fallback together; remove the corresponding portal lines in text too. Keep the PDF instruction, period, net salary and sign-off. Current callers do not deliver to a no-email employee, so that fixture is explicitly template-only. It must not imply a new recipient routing path.

The primary label Open payroll portal improves the source's visible site reference. Explain that it opens the Built payroll site; do not label it Download payslip or imply a specific document page. No separate legacy duplicate link fields exist: the new button/fallback share the same original literal destination.

Native Laravel integration and safe values

Portable {{placeholder_name}} tokens are not automatically Blade variables. Prefer a dedicated complete HTML Blade view plus a separate text view using the existing Mailable data. Preserve existing headers, queueing, PDF generation/naming and URL destination. Do not nest this document inside mail::message or introduce another templating framework. Follow the repository's Laravel integration guide.

Use escaped expressions for names, period, formatted salary and attributes. Validate the payroll URL's HTTPS scheme/host/path separately from escaping. Preserve complete source values and do not insert untrusted raw HTML. If portable replacement is chosen, use one pass so inserted token-like text is not re-evaluated. Remove unsupported optional sections wholly, not by leaving unresolved placeholders.

Default logo: https://built-storage.ams3.cdn.digitaloceanspaces.com/Built/app_name.png. Retain assets/brand/built-logo.png as the original source. Deployment uses absolute approved HTTPS hosting or a real matching CID attachment, with alt text, proportions and white backing preserved. Relative fixture paths belong only to preview output. Remote images may be blocked; native dark CSS is progressive enhancement.

Files and testing limits

public/ready/employee-payslip.html and .txt are standalone extracts; public/previews/employee-payslip-*.html/.txt are fictional populated states. No separate project-owned text alternative was found for the Markdown source, so the supplied .txt is a proposed equivalent.

No real employee salary/recipient data, PDFs, email sends or portal actions are used here. Preview links are local explanations. Browser rendering does not establish Gmail, Outlook, iOS Mail compatibility, actual PDF correctness, CID delivery or successful portal authentication. See the payslip batch and validation records for evidence and open decisions.