adrema/app/Invoice/InvoiceDocument.php

125 lines
3.2 KiB
PHP

<?php
namespace App\Invoice;
use App\Invoice\Models\Invoice;
use App\Payment\Payment;
use Exception;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
use Zoomyboy\Tex\Document;
use Zoomyboy\Tex\Engine;
use Zoomyboy\Tex\Template;
abstract class InvoiceDocument extends Document
{
abstract public function getSubject(): string;
abstract public function view(): string;
abstract public function afterSingle(Payment $payment): void;
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;
public string $until;
public string $filename;
/**
* @param array<string, string> $positions
*/
public function __construct(
public string $toName,
public string $toAddress,
public string $toZip,
public string $toLocation,
public string $greeting,
public array $positions,
public string $usage,
) {
$this->until = now()->addWeeks(2)->format('d.m.Y');
$this->filename = Str::slug("{$this->getSubject()} für {$toName}");
}
public static function fromInvoice(Invoice $invoice): self
{
return static::withoutMagicalCreationFrom([
'toName' => $invoice->to['name'],
'toAddress' => $invoice->to['address'],
'toZip' => $invoice->to['zip'],
'toLocation' => $invoice->to['location'],
'greeting' => $invoice->greeting,
'positions' => static::renderPositions($invoice),
'usage' => $invoice->usage,
]);
}
public function settings(): InvoiceSettings
{
return app(InvoiceSettings::class);
}
public function getEngine(): Engine
{
return Engine::PDFLATEX;
}
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
{
throw_unless($this->email, Exception::class, 'Cannot get Recipient. Mail not set.');
return new MailRecipient($this->email, $this->familyName);
}
/**
* @return view-string
*/
public function mailView(): string
{
$view = 'mail.payment.' . Str::snake(class_basename($this));
throw_unless(view()->exists($view), Exception::class, 'Mail view ' . $view . ' existiert nicht.');
return $view;
}
/**
* @return array<string, string>
*/
public static function renderPositions(Invoice $invoice): array
{
return $invoice->positions->mapWithKeys(fn ($position) => [$position->description => static::number($position->price)])->toArray();
}
public static function number(int $number): string
{
return number_format($number / 100, 2, '.', '');
}
}