212 lines
7.2 KiB
PHP
212 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace App\Model\Facade;
|
|
|
|
use Nette\Database\Explorer;
|
|
|
|
class FakturaFacade
|
|
{
|
|
public function __construct(
|
|
private Explorer $kufrikExplorer
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Vrátí seznam faktur s dopočítanou celkovou částkou z položek.
|
|
*/
|
|
public function getFiltered(?int $rok = null, string $mesic = ''): array
|
|
{
|
|
$where = [];
|
|
$params = [];
|
|
|
|
if ($rok) {
|
|
$where[] = 'YEAR(F.DATUM_VYSTAVENI) = ?';
|
|
$params[] = $rok;
|
|
}
|
|
|
|
if ($mesic !== '') {
|
|
$where[] = 'MONTH(F.DATUM_VYSTAVENI) = ?';
|
|
$params[] = (int) $mesic;
|
|
}
|
|
|
|
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
|
|
|
$sql = "
|
|
SELECT
|
|
F.*,
|
|
ISNULL((SELECT SUM(P.CENA) FROM dbo.POLOZKA P WHERE P.FAKTURA = F.ID), 0) AS CASTKA_CELKEM
|
|
FROM dbo.FAKTURA F
|
|
{$whereSql}
|
|
ORDER BY F.DATUM_VYSTAVENI DESC, F.ID DESC
|
|
";
|
|
|
|
return $this->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();
|
|
}
|
|
} |