176 lines
4.5 KiB
PHP
176 lines
4.5 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, $imageVars] = $this->view($faktura, $polozky);
|
|
|
|
return $this->pdfSestava->render(
|
|
$this->templateFile(),
|
|
$view,
|
|
'Faktura ' . (string) ($faktura->CISLO ?? ''),
|
|
$autoPrint,
|
|
'P',
|
|
$imageVars,
|
|
);
|
|
}
|
|
|
|
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{0: array<string, mixed>, 1: array<string, string>}
|
|
*/
|
|
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 ?? ''));
|
|
$cislo = (string) ($faktura->CISLO ?? '');
|
|
$ucet = trim((string) ($faktura->D_BANKA ?? ''));
|
|
$splatnost = self::asDate($faktura->DATUM_SPLATNOSTI ?? null);
|
|
|
|
$imageVars = [];
|
|
$qrPlatba = false;
|
|
if ($ucet !== '') {
|
|
$png = SpaydQr::png(
|
|
$ucet,
|
|
$celkem,
|
|
$cislo,
|
|
$splatnost,
|
|
'Faktura ' . $cislo,
|
|
);
|
|
if ($png !== null) {
|
|
$imageVars['qrplatba'] = $png;
|
|
$qrPlatba = true;
|
|
}
|
|
}
|
|
|
|
return [
|
|
[
|
|
'cislo' => $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' => $ucet,
|
|
],
|
|
'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) ?: []),
|
|
'qrPlatba' => $qrPlatba,
|
|
],
|
|
$imageVars,
|
|
];
|
|
}
|
|
|
|
private static function asDate(mixed $value): ?\DateTimeInterface
|
|
{
|
|
if ($value instanceof \DateTimeInterface) {
|
|
return $value;
|
|
}
|
|
if (!is_string($value) || trim($value) === '') {
|
|
return null;
|
|
}
|
|
$timestamp = strtotime($value);
|
|
|
|
return $timestamp ? (new \DateTimeImmutable())->setTimestamp($timestamp) : null;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|