documentBehind($emailLog); $this->recordReading($invoice); if ($request->has('pdf')) { return $invoice->getGeneratedPDFOrStream('invoice'); } $issuer = $invoice->company_id; return view('app')->with([ 'customer_logo' => get_company_setting('customer_portal_logo', $issuer), 'current_theme' => get_company_setting('customer_portal_theme', $issuer), ]); } /** * Serve the same document as JSON for the viewer shell, in the trimmed * portal shape. */ public function getInvoice(EmailLog $emailLog) { return InvoiceResource::make($this->documentBehind($emailLog)); } /** * Trade an email-log token for the document it was issued for. * * Holding the token is the whole credential, so the guard is narrow. The * log must point at a billing document (a token minted for some other * kind of mail must not disclose one, however the ids line up), and the * link must still be inside the company's expiry window. */ private function documentBehind(EmailLog $emailLog): Invoice { $document = $emailLog->mailable; if (! $document instanceof Invoice) { abort(404); } if ($emailLog->isExpired()) { abort(403, 'Link Expired.'); } return $document; } /** * Promote a document that is still awaiting a reader, and tell the issuer * about it when they asked to be told. */ private function recordReading(Invoice $invoice): void { $unread = [Invoice::STATUS_SENT, Invoice::STATUS_DRAFT]; if (! in_array($invoice->status, $unread)) { return; } $invoice->update([ 'status' => Invoice::STATUS_VIEWED, 'viewed' => true, ]); $wanted = CompanySetting::getSetting('notify_invoice_viewed', $invoice->company_id); if ($wanted != 'YES') { return; } $payload = [ 'invoice' => Invoice::findOrFail($invoice->id)->toArray(), 'user' => Customer::find($invoice->customer_id)->toArray(), ]; $mailbox = CompanySetting::getSetting('notification_email', $invoice->company_id); Mail::to($mailbox)->send(new InvoiceViewedMail($payload)); } }