Kufrik/app/Model/Faktura/FakturaPdf.php

138 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Model\Faktura;
/**
* Sestava faktury podle rptFaktura3 (PDF, tisk).
*/
final class FakturaPdf
{
private const FORMY_UHRADY = [
1 => 'převodem',
2 => 'hotově',
];
public function __construct(
private PdfSestava $pdfSestava,
) {
}
/**
* @param array<int, object> $polozky
*/
public function render(object $faktura, array $polozky, bool $autoPrint = false): string
{
$view = $this->view($faktura, $polozky);
return $this->pdfSestava->render(
$this->templateFile(),
$view,
'Faktura ' . (string) ($faktura->CISLO ?? ''),
$autoPrint,
);
}
public static function fileName(string $cislo): string
{
$safe = preg_replace('/[^\p{L}\p{N}._-]+/u', '_', trim($cislo)) ?? '';
$safe = trim($safe, '._');
return 'Faktura_' . ($safe !== '' ? $safe : 'doklad') . '.pdf';
}
/**
* @param array<int, object> $polozky
* @return array<string, mixed>
*/
private function view(object $faktura, array $polozky): array
{
$radky = [];
$celkem = 0.0;
foreach ($polozky as $polozka) {
$cena = (float) ($polozka->CENA ?? 0);
$celkem += $cena;
$radky[] = [
'nazev' => (string) ($polozka->NAZEV ?? ''),
'pocet' => self::formatQty($polozka->POCET ?? 0),
'jednotka' => (string) ($polozka->JEDNOTKA ?? ''),
'cenaJednotka' => self::formatMoney($polozka->CENA_JEDNOTKA ?? 0),
'sleva' => self::formatQty($polozka->SLEVA ?? 0) . ' %',
'cena' => self::formatMoney($cena),
];
}
$cinnosti = trim((string) ($faktura->CINNOSTI ?? ''));
return [
'cislo' => (string) ($faktura->CISLO ?? ''),
'dodavatel' => [
'nazev' => (string) ($faktura->D_PRAJM ?? ''),
'ulice' => (string) ($faktura->D_ULICE ?? ''),
'psc' => (string) ($faktura->D_PSC ?? ''),
'mesto' => (string) ($faktura->D_MESTO ?? ''),
'telefon' => (string) ($faktura->D_TELEFON ?? ''),
'email' => (string) ($faktura->D_EMAIL ?? ''),
'web' => (string) ($faktura->D_WEB ?? ''),
'ic' => (string) ($faktura->D_IC ?? ''),
'ucet' => (string) ($faktura->D_BANKA ?? ''),
],
'odberatel' => [
'nazev' => (string) ($faktura->O_PRAJM ?? ''),
'ulice' => (string) ($faktura->O_ULICE ?? ''),
'psc' => (string) ($faktura->O_PSC ?? ''),
'mesto' => (string) ($faktura->O_MESTO ?? ''),
'ic' => (string) ($faktura->O_IC ?? ''),
'dic' => self::formatDic($faktura->O_DIC ?? null),
],
'datumVystaveni' => self::formatDate($faktura->DATUM_VYSTAVENI ?? null),
'datumSplatnosti' => self::formatDate($faktura->DATUM_SPLATNOSTI ?? null),
'formaUhrady' => self::FORMY_UHRADY[(int) ($faktura->FORMA_UHRADY ?? 0)] ?? '',
'polozky' => $radky,
'celkem' => 'Celkem: ' . self::formatMoney($celkem),
'cinnosti' => $cinnosti === '' ? [] : (preg_split("/\R/u", $cinnosti) ?: []),
];
}
private function templateFile(): string
{
return __DIR__ . DIRECTORY_SEPARATOR . 'faktura.latte';
}
private static function formatDate(mixed $value): string
{
if ($value instanceof \DateTimeInterface) {
return $value->format('d.m.Y');
}
if (!is_string($value) || trim($value) === '') {
return '';
}
$timestamp = strtotime($value);
return $timestamp ? date('d.m.Y', $timestamp) : $value;
}
private static function formatMoney(mixed $value): string
{
return number_format((float) $value, 2, ',', ' ') . ' Kč';
}
private static function formatQty(mixed $value): string
{
$formatted = number_format((float) $value, 2, ',', ' ');
return rtrim(rtrim($formatted, '0'), ',');
}
private static function formatDic(mixed $value): string
{
$dic = trim((string) $value);
if ($dic === '' || preg_match('/^[A-Za-z]{2}/', $dic)) {
return $dic;
}
return 'CZ' . $dic;
}
}