From 7a98fb3f534a7184d151af17d7bd4df9865c116a Mon Sep 17 00:00:00 2001 From: Kowalski Date: Tue, 1 Sep 2026 18:35:12 +0200 Subject: [PATCH] Filtr faktur. --- app/Model/Facade/FakturaFacade.php | 34 +++++++- app/UI/@layout.latte | 35 ++++---- app/UI/Faktura/FakturaPresenter.php | 122 +++++++++++++++++++++++++--- app/UI/Faktura/default.latte | 31 ++++--- 4 files changed, 176 insertions(+), 46 deletions(-) diff --git a/app/Model/Facade/FakturaFacade.php b/app/Model/Facade/FakturaFacade.php index 41df1e4..ea68392 100644 --- a/app/Model/Facade/FakturaFacade.php +++ b/app/Model/Facade/FakturaFacade.php @@ -24,9 +24,10 @@ class FakturaFacade $params[] = $rok; } - if ($mesic !== '') { + $mesicCislo = (int) $mesic; + if ($mesic !== '' && $mesicCislo >= 1 && $mesicCislo <= 12) { $where[] = 'MONTH(F.DATUM_VYSTAVENI) = ?'; - $params[] = (int) $mesic; + $params[] = $mesicCislo; } $whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : ''; @@ -43,6 +44,35 @@ class FakturaFacade return $this->kufrikExplorer->query($sql, ...$params)->fetchAll(); } + /** + * Roky, pro které existují faktury (plus aktuální / právě vybraný rok). + * + * @return int[] + */ + public function getDostupneRoky(?int $vybranyRok = null): array + { + $rows = $this->kufrikExplorer->query(" + SELECT DISTINCT YEAR(DATUM_VYSTAVENI) AS ROK + FROM dbo.FAKTURA + WHERE DATUM_VYSTAVENI IS NOT NULL + ORDER BY ROK DESC + ")->fetchAll(); + + $roky = []; + foreach ($rows as $row) { + $roky[] = (int) $row->ROK; + } + + foreach ([(int) date('Y'), $vybranyRok] as $rok) { + if ($rok && !in_array($rok, $roky, true)) { + $roky[] = $rok; + } + } + + rsort($roky, SORT_NUMERIC); + return $roky; + } + /** * Detail jedné faktury podle ID */ diff --git a/app/UI/@layout.latte b/app/UI/@layout.latte index 81cfc58..b49d9b6 100644 --- a/app/UI/@layout.latte +++ b/app/UI/@layout.latte @@ -135,35 +135,34 @@ -
+ {var $aktualniRok = (int) date('Y')} - {var $vybranyRok = $presenter->rok ?? $aktualniRok} - {var $vybranyMesic = $presenter->mesic ?? ''} + {var $vybranyRok = $selectedRok ?? $aktualniRok} + {var $vybranyMesic = (string) ($selectedMesic ?? '')} + {var $rokyFiltr = $roky ?? range($aktualniRok, $aktualniRok - 3)}
diff --git a/app/UI/Faktura/FakturaPresenter.php b/app/UI/Faktura/FakturaPresenter.php index dd7f26d..4ae9584 100644 --- a/app/UI/Faktura/FakturaPresenter.php +++ b/app/UI/Faktura/FakturaPresenter.php @@ -4,29 +4,60 @@ namespace App\UI\Faktura; use App\UI\BasePresenter; use App\Model\Facade\FakturaFacade; +use Nette\Application\Attributes\Persistent; class FakturaPresenter extends BasePresenter { - /** @persistent */ - public int $rok; + private const FILTER_COOKIE = 'kufrikFakturaFiltr'; + private const FILTER_SESSION = 'fakturaFilter'; - /** @persistent */ + #[Persistent] + public ?int $rok = null; + + #[Persistent] public string $mesic = ''; public function __construct( private FakturaFacade $fakturaFacade ) { parent::__construct(); - $this->rok = (int) date('Y'); + } + + protected function startup(): void + { + parent::startup(); + + $query = $this->getHttpRequest()->getQuery(); + $fromUrl = array_key_exists('rok', $query) || array_key_exists('mesic', $query); + + if ($fromUrl) { + $this->rok = $this->rok ?? (int) date('Y'); + $this->mesic = $this->normalizeMesic($this->mesic); + $this->saveFilter($this->rok, $this->mesic); + return; + } + + $saved = $this->loadFilter(); + if ($saved === null) { + return; + } + + $this->rok = $saved['rok']; + $this->mesic = $saved['mesic']; + + // Do URL doplníme uložený filtr, ale ne při signálu (úhrada / smazání). + if ($this->getSignal() === null) { + $this->redirect('this'); + } } public function renderDefault(): void { - // RLS v databázi se postará o filtraci podle firmy, - // fasáda vrátí seřazené faktury s dopočítanou sumou. - $faktury = $this->fakturaFacade->getFiltered($this->rok, $this->mesic); + $rok = $this->rok ?? (int) date('Y'); + $mesic = $this->normalizeMesic($this->mesic); + + $faktury = $this->fakturaFacade->getFiltered($rok, $mesic); - // Agregace pro přehledové karty nad aktuálním výběrem $celkemSum = 0; $neuhrazenoCount = 0; @@ -40,8 +71,79 @@ class FakturaPresenter extends BasePresenter $this->template->faktury = $faktury; $this->template->celkemSum = $celkemSum; $this->template->neuhrazenoCount = $neuhrazenoCount; - $this->template->selectedRok = $this->rok ?? (int) date('Y'); // <--- PŘIDÁNO - $this->template->selectedMesic = $this->mesic ?? ''; // <--- PŘIDÁNO + $this->template->selectedRok = $rok; + $this->template->selectedMesic = $mesic; + $this->template->roky = $this->fakturaFacade->getDostupneRoky($rok); + } + + private function normalizeMesic(string $mesic): string + { + if ($mesic === '') { + return ''; + } + + $cislo = (int) $mesic; + return ($cislo >= 1 && $cislo <= 12) ? (string) $cislo : ''; + } + + /** + * @return array{rok: int, mesic: string}|null + */ + private function loadFilter(): ?array + { + $uid = (int) $this->getUser()->getId(); + $section = $this->getSession(self::FILTER_SESSION); + + if (isset($section->rok) && (int) ($section->userId ?? 0) === $uid) { + return $this->validFilter((int) $section->rok, (string) ($section->mesic ?? '')); + } + + $raw = $this->getHttpRequest()->getCookie(self::FILTER_COOKIE); + if (!is_string($raw) || $raw === '') { + return null; + } + + $parts = explode(':', $raw, 3); + if (count($parts) < 2 || (int) $parts[0] !== $uid) { + return null; + } + + return $this->validFilter((int) $parts[1], (string) ($parts[2] ?? '')); + } + + private function saveFilter(int $rok, string $mesic): void + { + $uid = (int) $this->getUser()->getId(); + $section = $this->getSession(self::FILTER_SESSION); + $section->userId = $uid; + $section->rok = $rok; + $section->mesic = $mesic; + + $this->getHttpResponse()->setCookie( + self::FILTER_COOKIE, + $uid . ':' . $rok . ':' . $mesic, + '1 year', + null, + null, + null, + true, + 'Lax' + ); + } + + /** + * @return array{rok: int, mesic: string}|null + */ + private function validFilter(int $rok, string $mesic): ?array + { + if ($rok < 2000 || $rok > 2100) { + return null; + } + + return [ + 'rok' => $rok, + 'mesic' => $this->normalizeMesic($mesic), + ]; } /** diff --git a/app/UI/Faktura/default.latte b/app/UI/Faktura/default.latte index 4302753..7ce8b14 100644 --- a/app/UI/Faktura/default.latte +++ b/app/UI/Faktura/default.latte @@ -30,31 +30,30 @@
-
+