<?php namespace App\Invoice; use App\Payment\Payment; use Carbon\Carbon; use Exception; use Generator; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Collection; use Illuminate\Support\Str; use Zoomyboy\Tex\Document; use Zoomyboy\Tex\Engine; use Zoomyboy\Tex\Template; abstract class Invoice extends Document { abstract public function getSubject(): string; abstract public function view(): string; abstract public function linkLabel(): string; abstract public static function sendAllLabel(): string; /** * @param HasMany<Payment> $query * * @return HasMany<Payment> */ abstract public static function paymentsQuery(HasMany $query): HasMany; /** * @return array<int, string> */ abstract public static function getDescription(): array; abstract public function afterSingle(Payment $payment): void; /** * @var Collection<int, Page> */ public Collection $pages; public string $subject; protected string $filename; public string $until; public InvoiceSettings $settings; /** * @param Collection<int, Page> $pages */ public function __construct(Collection $pages) { $this->pages = $pages; $this->subject = $this->getSubject(); $this->until = now()->addWeeks(2)->format('d.m.Y'); $this->setFilename(Str::slug("{$this->getSubject()} für {$pages->first()?->familyName}")); $this->settings = app(InvoiceSettings::class); } public function number(int $number): string { return number_format($number / 100, 2, '.', ''); } public function getUntil(): Carbon { return now()->addWeeks(2); } public function getEngine(): Engine { return Engine::XELATEX; } public function basename(): string { return $this->filename; } public function template(): Template { return Template::make('tex.templates.default'); } public function setFilename(string $filename): self { $this->filename = $filename; return $this; } public function getRecipient(): MailRecipient { if (!$this->pages->first()?->email) { throw new Exception('Cannot get Recipient. Mail not set.'); } return new MailRecipient($this->pages->first()->email, $this->pages->first()->familyName); } public function allPayments(): Generator { foreach ($this->pages as $page) { foreach ($page->getPayments() as $payment) { yield $payment; } } } /** * @return view-string */ public function mailView(): string { $view = 'mail.payment.'.Str::snake(class_basename($this)); if (!view()->exists($view)) { throw new Exception('Mail view '.$view.' existiert nicht.'); } return $view; } }