kufrikExplorer->query($sql, ...$params)->fetchAll(); } /** * Detail jedné faktury podle ID */ public function getById(int $id) { return $this->kufrikExplorer->table('FAKTURA')->where('ID', $id)->fetch(); } /** * Položky faktury seřazené podle PORADI */ public function getPolozky(int $fakturaId): array { return $this->kufrikExplorer->query(" SELECT P.* FROM dbo.POLOZKA P WHERE P.FAKTURA = ? ORDER BY P.PORADI ASC, P.ID ASC ", $fakturaId)->fetchAll(); } /** * Vygeneruje následující číslo faktury pro aktuální rok a firmu */ public function getNextCislo(int $firmaId): string { $aktualniRok = (int) date('Y'); // Najdeme nejvyšší CISLO_ABS pro daný rok a firmu $maxAbs = $this->kufrikExplorer->query(" SELECT MAX(CISLO_ABS) AS MAX_ABS FROM dbo.FAKTURA WHERE FIRMA_ID = ? AND YEAR(DATUM_VYSTAVENI) = ? ", $firmaId, $aktualniRok)->fetch()?->MAX_ABS; // Pokud ještě v tomto roce žádná faktura neexistuje, začínáme od 1 $dalsiCislo = ($maxAbs !== null) ? ((int) $maxAbs + 1) : 1; // Formátování: RRRR + třímístné číslo doplněné nulami (např. 2026001, 2026002...) return $aktualniRok . str_pad((string) $dalsiCislo, 3, '0', STR_PAD_LEFT); } /** * Uložení / Aktualizace hlavičky faktury + vytvoření snapshotů D_* a O_* */ public function saveFaktura(array $data, ?int $id = null, int $firmaId): int { if ($id) { // PŘI EDITACI: Mění se pouze měnitelné údaje (splatnost, DUZP, stav, činnosti) $values = [ 'DATUM_SPLATNOSTI' => $data['DATUM_SPLATNOSTI'], 'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null, 'STAV' => $data['STAV'] ?? 'ISSUED', 'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null, ]; $this->kufrikExplorer->table('FAKTURA')->where('ID', $id)->update($values); return $id; } else { // PŘI NOVÉ FAKTUŘE: Ukládáme vše (včetně DATUM_VYSTAVENI, CISLO, ZAKAZNIK a snapshotů) $firma = $this->kufrikExplorer->table('FIRMA')->where('ID', $firmaId)->fetch(); $zakaznikId = !empty($data['ZAKAZNIK_ID']) ? (int) $data['ZAKAZNIK_ID'] : null; $zakaznik = $zakaznikId ? $this->kufrikExplorer->table('ZAKAZNIK')->where('ID', $zakaznikId)->fetch() : null; $oPrajm = $zakaznik ? trim(($zakaznik->PRIJMENI ?? '') . ' ' . ($zakaznik->JMENO ?? '')) : null; $dBanka = null; if ($firma) { if (isset($firma->UCET, $firma->KOD_BANKY) && $firma->UCET) { $dBanka = $firma->UCET . '/' . $firma->KOD_BANKY; } elseif (isset($firma->BANKA)) { $dBanka = $firma->BANKA; } } $values = [ 'FIRMA_ID' => $firmaId, 'ZAKAZNIK' => $zakaznikId, 'CISLO' => $data['CISLO'], 'CISLO_ABS' => (int) ($data['CISLO_ABS'] ?? substr($data['CISLO'], -3)), 'FORMA_UHRADY' => (int) ($data['FORMA_UHRADY'] ?? 1), 'DATUM_VYSTAVENI' => $data['DATUM_VYSTAVENI'], 'DATUM_SPLATNOSTI' => $data['DATUM_SPLATNOSTI'], 'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null, 'STAV' => $data['STAV'] ?? 'ISSUED', 'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null, // SNAPSHOT DODAVATELE 'D_PRAJM' => $firma->NAZEV ?? null, 'D_ULICE' => $firma->ULICE ?? null, 'D_MESTO' => $firma->MESTO ?? null, 'D_PSC' => $firma->PSC ?? null, 'D_IC' => $firma->IC ?? null, 'D_DIC' => $firma->DIC ?? null, 'D_BANKA' => $dBanka, 'D_TELEFON' => $firma->TELEFON ?? null, 'D_EMAIL' => $firma->EMAIL ?? null, 'D_WEB' => $firma->WEB ?? null, // SNAPSHOT ODBĚRATELE 'O_PRAJM' => $oPrajm, 'O_ULICE' => $zakaznik->ULICE ?? null, 'O_MESTO' => $zakaznik->MESTO ?? null, 'O_PSC' => $zakaznik->PSC ?? null, 'O_IC' => $zakaznik->IC ?? null, 'O_DIC' => $zakaznik->DIC ?? null, ]; $row = $this->kufrikExplorer->table('FAKTURA')->insert($values); return $row->ID; } } /** * Uložení položek s automatickým výpočtem PORADI */ public function savePolozky(int $fakturaId, array $polozkyData, int $firmaId): void { $this->kufrikExplorer->table('POLOZKA')->where('FAKTURA', $fakturaId)->delete(); $poradi = 1; foreach ($polozkyData as $item) { if (empty($item['NAZEV']) && empty($item['CENA_JEDNOTKA'])) { continue; } $pocet = (float) ($item['POCET'] ?? 1); $cenaJednotka = (float) ($item['CENA_JEDNOTKA'] ?? 0); $sleva = (float) ($item['SLEVA'] ?? 0); $cenaCelkem = ($pocet * $cenaJednotka) * (1 - ($sleva / 100)); $this->kufrikExplorer->table('POLOZKA')->insert([ 'FAKTURA' => $fakturaId, 'FIRMA_ID' => $firmaId, 'PORADI' => $poradi++, 'NAZEV' => $item['NAZEV'], 'POCET' => $pocet, 'JEDNOTKA' => $item['JEDNOTKA'] ?: 'ks', 'CENA_JEDNOTKA' => $cenaJednotka, 'SLEVA' => $sleva, 'CENA' => $cenaCelkem, ]); } } public function toggleUhrada(int $id): string { $faktura = $this->getById($id); if (!$faktura) { return ''; } $novyStav = ($faktura->STAV === 'PAID') ? 'ISSUED' : 'PAID'; $this->kufrikExplorer->table('FAKTURA') ->where('ID', $id) ->update(['STAV' => $novyStav]); return $novyStav; } public function delete(int $id): void { $this->kufrikExplorer->table('FAKTURA')->where('ID', $id)->delete(); } }