| Server IP : 193.86.120.172 / Your IP : 216.73.216.67 Web Server : Apache/2.4.63 (Unix) System : Linux JServices 3.10.108 #86003 SMP Wed Oct 22 13:20:46 CST 2025 x86_64 User : kubec ( 1026) PHP Version : 8.2.28 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /volume1/web/hotel_jservices_cz/api/ |
Upload File : |
<?php
// ============================================================
// Hotel DEMO — api/rezervace.php
// CRUD rezervací, změna stavu, check-in/out časy, slevy
// ============================================================
require_once __DIR__ . '/../includes/mailer.php';
$action = $_GET['action'] ?? '';
$input = json_decode(file_get_contents('php://input'), true) ?? [];
// Veřejné akce nevyžadují přihlášení (zákazník přes rezervační formulář)
$verejne_akce = ['vytvorit'];
$user = in_array($action, $verejne_akce) ? null : auth_check();
match ($action) {
'seznam' => rez_seznam($user),
'detail' => rez_detail($user, (int)($_GET['id'] ?? 0)),
'vytvorit' => rez_vytvorit($user, $input),
'upravit' => rez_upravit($user, (int)($_GET['id'] ?? 0), $input),
'potvrdit' => rez_potvrdit($user, (int)($_GET['id'] ?? 0), $input),
'upravit-hosta' => rez_upravit_hosta($user, (int)($_GET['id'] ?? 0), $input),
'odebrat-doplnek' => rez_odebrat_doplnek($user, (int)($_GET['id'] ?? 0), $input),
'zmenit-pokoj' => rez_zmenit_pokoj($user, (int)($_GET['id'] ?? 0), $input),
'schvalit-pokoj' => rez_schvalit_pokoj($user, (int)($_GET['id'] ?? 0)),
'zamitnout-pokoj' => rez_zamitnout_pokoj($user, (int)($_GET['id'] ?? 0), $input),
'pridat-doplnek' => rez_pridat_doplnek($user, (int)($_GET['id'] ?? 0), $input),
'zrusit' => rez_zrusit($user, (int)($_GET['id'] ?? 0), $input),
'checkin-cas' => rez_checkinout_cas($user, (int)($_GET['id'] ?? 0), 'checkin', $input),
'checkout-cas' => rez_checkinout_cas($user, (int)($_GET['id'] ?? 0), 'checkout', $input),
'schvalit-cas' => rez_schvalit_cas($user, (int)($_GET['id'] ?? 0), $input),
'zamitnout-cas' => rez_zamitnout_cas($user, (int)($_GET['id'] ?? 0), $input),
'navrhnout-slevu' => rez_navrhnout_slevu($user, (int)($_GET['id'] ?? 0), $input),
'schvalit-slevu' => rez_rozhodnout_slevu($user, (int)($_GET['id'] ?? 0), true, $input),
'zamitnout-slevu' => rez_rozhodnout_slevu($user, (int)($_GET['id'] ?? 0), false, $input),
'cena-override' => rez_cena_override($user, (int)($_GET['id'] ?? 0), $input),
'dnes' => rez_dnes($user),
'today' => rez_dnes($user),
default => api_response(false, null, 'Neznámá akce', 400),
};
// ------------------------------------------------------------
// SEZNAM
// ------------------------------------------------------------
function rez_seznam(array $user): never {
$stav = $_GET['stav'] ?? '';
$datum_od = $_GET['datum_od'] ?? '';
$datum_do = $_GET['datum_do'] ?? '';
$pokoj_id = (int)($_GET['pokoj_id'] ?? 0);
$search = trim($_GET['search'] ?? '');
$limit = min((int)($_GET['limit'] ?? 50), 200);
$offset = (int)($_GET['offset'] ?? 0);
$where = ['1=1'];
$params = [];
if ($stav) { $where[] = 'r.stav = ?'; $params[] = $stav; }
if ($datum_od) { $where[] = 'r.datum_prijezdu >= ?'; $params[] = $datum_od; }
if ($datum_do) { $where[] = 'r.datum_odjezdu <= ?'; $params[] = $datum_do; }
if ($pokoj_id) { $where[] = 'r.pokoj_id = ?'; $params[] = $pokoj_id; }
if ($search) {
$where[] = '(r.jmeno LIKE ? OR r.prijmeni LIKE ? OR r.email LIKE ? OR r.telefon LIKE ? OR r.id = ?)';
$s = '%' . $search . '%';
$id_search = ctype_digit($search) ? (int)$search : 0;
$params = array_merge($params, [$s, $s, $s, $s, $id_search]);
}
$sql_where = implode(' AND ', $where);
$celkem = (int)db_val("SELECT COUNT(*) FROM rezervace r WHERE {$sql_where}", $params);
$rezervace = db_rows(
"SELECT r.id, r.pokoj_id, r.datum_prijezdu, r.datum_odjezdu, r.pocet_noci,
r.jmeno, r.prijmeni, r.email, r.telefon, r.pocet_hostu, r.jazyk,
r.stav, r.cena_zaklad, r.cena_upravena,
r.sleva_castka, r.sleva_stav, r.na_firmu, r.firma,
r.checkin_cas, r.checkout_cas, r.vytvoreno,
r.cas_zadost_typ, r.cas_zadost_hodnota, r.cas_zadost_stav, r.cas_zadost_poznamka,
r.pokoj_zadost_pokoj_id, r.pokoj_zadost_cena_typu, r.pokoj_zadost_stav, r.pokoj_zadost_poznamka,
r.sleva_manazer_poznamka,
p.cislo AS pokoj_cislo,
COALESCE(p.nazev, CONCAT('Pokoj ', p.cislo)) AS pokoj_nazev,
t.nazev AS typ_nazev
FROM rezervace r
JOIN pokoje p ON p.id = r.pokoj_id
JOIN typy_pokoju t ON t.id = p.typ_id
WHERE {$sql_where}
ORDER BY r.datum_prijezdu DESC
LIMIT {$limit} OFFSET {$offset}",
$params
);
api_response(true, ['rezervace' => $rezervace, 'celkem' => $celkem,
'limit' => $limit, 'offset' => $offset]);
}
// ------------------------------------------------------------
// DETAIL
// ------------------------------------------------------------
function rez_detail(array $user, int $id): never {
if (!$id) api_response(false, null, 'Chybí ID', 400);
$rez = db_row(
"SELECT r.*,
p.cislo AS pokoj_cislo,
COALESCE(p.nazev, CONCAT('Pokoj ', p.cislo)) AS pokoj_nazev,
p.typ_id,
t.nazev AS typ_nazev, t.kapacita, t.cena_za_noc,
CONCAT(u.jmeno, ' ', u.prijmeni) AS vytvoril_jmeno,
CONCAT(ci.jmeno, ' ', ci.prijmeni) AS checkin_zmenil_jmeno,
CONCAT(co.jmeno, ' ', co.prijmeni) AS checkout_zmenil_jmeno,
CONCAT(sl.jmeno, ' ', sl.prijmeni) AS sleva_schvalil_jmeno
FROM rezervace r
JOIN pokoje p ON p.id = r.pokoj_id
JOIN typy_pokoju t ON t.id = p.typ_id
LEFT JOIN uzivatele u ON u.id = r.vytvoril_id
LEFT JOIN uzivatele ci ON ci.id = r.checkin_zmenil_id
LEFT JOIN uzivatele co ON co.id = r.checkout_zmenil_id
LEFT JOIN uzivatele sl ON sl.id = r.sleva_schvalil_id
WHERE r.id = ?",
[$id]
);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 404);
$doplnky = db_rows('SELECT * FROM rezervace_doplnky WHERE rezervace_id = ?', [$id]);
$hodnoceni = db_row('SELECT hvezdicky, vytvoreno FROM hodnoceni WHERE rezervace_id = ?', [$id]);
api_response(true, ['rezervace' => $rez, 'doplnky' => $doplnky, 'hodnoceni' => $hodnoceni]);
}
// ------------------------------------------------------------
// VYTVOŘENÍ
// ------------------------------------------------------------
function rez_vytvorit(?array $user, array $input): never {
$data = _rez_validuj($input, $user);
// Automatické přiřazení konkrétního pokoje dle typu
$pokoj_id = _rez_prirad_pokoj($data['typ_id'], $data['datum_prijezdu'], $data['datum_odjezdu']);
if (!$pokoj_id) {
api_response(false, null, 'Vybraný typ pokoje není v tomto termínu dostupný. Zkuste jiný termín nebo typ pokoje.', 409);
}
$data['pokoj_id'] = $pokoj_id;
// Cena pokoje (snapshot z typu)
$cena_za_noc = (float)db_val('SELECT cena_za_noc FROM typy_pokoju WHERE id = ?', [$data['typ_id']]);
$cena_zaklad = round($cena_za_noc * $data['pocet_noci'], 2);
// Automatická sleva pro 1 hosta ve vícelůžkovém pokoji
$sleva_castka = null;
$sleva_stav = null;
$sleva_poznamka = null;
$sleva_jl = 0;
$kapacita = (int)db_val('SELECT kapacita FROM typy_pokoju WHERE id = ?', [$data['typ_id']]);
if ($data['pocet_hostu'] === 1 && $kapacita > 1) {
$sleva_zapnuta = nastaveni('sleva_jednoluzko_zapnuta', '1') === '1';
$sleva_procent = (int)nastaveni('sleva_jednoluzko_procent', '20');
if ($sleva_zapnuta && $sleva_procent > 0) {
$sleva_castka = round($cena_zaklad * $sleva_procent / 100, 2);
$sleva_stav = 'schvalena';
$sleva_poznamka = 'Automatická sleva ' . $sleva_procent . ' % — 1 host ve vícelůžkovém pokoji';
$sleva_jl = 1;
}
}
$token = bin2hex(random_bytes(32));
$id = db_insert(
'INSERT INTO rezervace
(pokoj_id, datum_prijezdu, datum_odjezdu, pocet_noci,
jmeno, prijmeni, email, telefon, pocet_hostu, poznamka,
na_firmu, firma, ico, dic, faktura_ulice, faktura_psc, faktura_mesto,
stav, cena_zaklad, sleva_castka, sleva_stav, sleva_poznamka,
sleva_jednoluzko, token_zmena, vytvoril_id, jazyk)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
[
$data['pokoj_id'], $data['datum_prijezdu'], $data['datum_odjezdu'], $data['pocet_noci'],
$data['jmeno'], $data['prijmeni'], $data['email'], $data['telefon'],
$data['pocet_hostu'], $data['poznamka'],
$data['na_firmu'], $data['firma'], $data['ico'], $data['dic'],
$data['faktura_ulice'], $data['faktura_psc'], $data['faktura_mesto'],
'ceka', $cena_zaklad, $sleva_castka, $sleva_stav, $sleva_poznamka,
$sleva_jl, $token, $user['id'] ?? null, $data['jazyk'],
]
);
if (!empty($input['doplnky'])) {
_rez_uloz_doplnky($id, $input['doplnky'], $data['pocet_noci'], $data['pocet_hostu']);
}
_rez_upsert_zakaznik($data);
// Odeslat e-mail - chyba nesmí přerušit JSON odpověď
ob_start();
try {
odeslat_potvrzeni_rezervace($id);
error_log('[Rezervace] E-mail odeslán pro #' . $id);
} catch (\Throwable $e) {
error_log('[Rezervace] E-mail selhal pro #' . $id . ': ' . $e->getMessage());
} finally {
ob_end_clean();
}
api_response(true, ['id' => $id, 'token' => $token]);
}
// ------------------------------------------------------------
// ÚPRAVA
// ------------------------------------------------------------
function rez_upravit(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID', 400);
if ($user['role'] === 'zamestnanec' && !auth_has_opravneni($user, 'zmena_rezervace')) {
api_response(false, null, 'Nemáte oprávnění upravovat rezervace.', 403);
}
$rez = db_row('SELECT * FROM rezervace WHERE id = ?', [$id]);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 404);
if ($rez['stav'] === 'zrusena') api_response(false, null, 'Zrušenou rezervaci nelze upravit.', 400);
$data = _rez_validuj($input, $user);
// Pro úpravu zachováme stávající pokoj pokud se termín nemění
$meni_termin = $data['typ_id'] !== (int)db_val('SELECT typ_id FROM pokoje WHERE id = ?', [$rez['pokoj_id']])
|| $data['datum_prijezdu'] !== $rez['datum_prijezdu']
|| $data['datum_odjezdu'] !== $rez['datum_odjezdu'];
if ($meni_termin) {
$pokoj_id = _rez_prirad_pokoj($data['typ_id'], $data['datum_prijezdu'], $data['datum_odjezdu'], $id);
if (!$pokoj_id) api_response(false, null, 'Zvolený typ pokoje není v tomto termínu dostupný.', 409);
$data['pokoj_id'] = $pokoj_id;
} else {
$data['pokoj_id'] = (int)$rez['pokoj_id'];
}
$cena_zaklad = (float)$rez['cena_zaklad'];
if ($meni_termin) {
$cena_za_noc = (float)db_val('SELECT cena_za_noc FROM typy_pokoju WHERE id = ?', [$data['typ_id']]);
$cena_zaklad = round($cena_za_noc * $data['pocet_noci'], 2);
}
db_query(
'UPDATE rezervace SET
pokoj_id=?, datum_prijezdu=?, datum_odjezdu=?, pocet_noci=?,
jmeno=?, prijmeni=?, email=?, telefon=?, pocet_hostu=?, poznamka=?,
na_firmu=?, firma=?, ico=?, dic=?, faktura_ulice=?, faktura_psc=?, faktura_mesto=?,
cena_zaklad=?
WHERE id=?',
[
$data['pokoj_id'], $data['datum_prijezdu'], $data['datum_odjezdu'], $data['pocet_noci'],
$data['jmeno'], $data['prijmeni'], $data['email'], $data['telefon'],
$data['pocet_hostu'], $data['poznamka'],
$data['na_firmu'], $data['firma'], $data['ico'], $data['dic'],
$data['faktura_ulice'], $data['faktura_psc'], $data['faktura_mesto'],
$cena_zaklad, $id,
]
);
if (isset($input['doplnky'])) {
db_query('DELETE FROM rezervace_doplnky WHERE rezervace_id = ?', [$id]);
if (!empty($input['doplnky'])) {
_rez_uloz_doplnky($id, $input['doplnky'], $data['pocet_noci'], $data['pocet_hostu']);
}
}
if ($meni_termin) {
try { odeslat_zmenu_terminu($id); } catch (\Exception $e) { error_log($e->getMessage()); }
}
api_response(true, null);
}
// ------------------------------------------------------------
// ZRUŠENÍ
// ------------------------------------------------------------
function rez_zrusit(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID', 400);
if ($user['role'] === 'zamestnanec' && !auth_has_opravneni($user, 'storno_rezervace')) {
api_response(false, null, 'Nemáte oprávnění rušit rezervace.', 403);
}
$rez = db_row('SELECT * FROM rezervace WHERE id = ?', [$id]);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 404);
if ($rez['stav'] === 'zrusena') api_response(false, null, 'Rezervace je již zrušena.', 400);
$duvod = trim($input['duvod'] ?? '');
db_query("UPDATE rezervace SET stav='zrusena', duvod_zruseni=? WHERE id=?", [$duvod ?: null, $id]);
// Interní storno (zaměstnanec/manažer):
// - hotel_email (sdílená recepční schránka) se nikdy nenotifikuje — storno udělal personál
// - manažeři s vlastní preferencí notif_storno chtějí přehled bez ohledu na to, kdo storno udělal,
// takže pokud storno provedl zaměstnanec, manažeři se notifikují; pokud storno provedl
// sám manažer/admin, notifikace ostatním manažerům jde také (nemá smysl ji blokovat).
try {
odeslat_storno($id, notifikovat_hotel: false, notifikovat_manazery: true);
} catch (\Exception $e) { error_log($e->getMessage()); }
api_response(true, null);
}
// ------------------------------------------------------------
// ZMĚNA CHECK-IN / CHECK-OUT ČASU
// ------------------------------------------------------------
function rez_checkinout_cas(array $user, int $id, string $typ, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID', 400);
if ($user['role'] === 'zamestnanec' && !auth_has_opravneni($user, 'zmena_terminu')) {
api_response(false, null, 'Nemáte oprávnění měnit časy příjezdu/odjezdu.', 200);
}
$rez = db_row('SELECT * FROM rezervace WHERE id = ?', [$id]);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 404);
$cas = trim($input['cas'] ?? '');
if (!preg_match('/^\d{2}:\d{2}$/', $cas)) {
api_response(false, null, 'Neplatný formát času (HH:MM).', 400);
}
// Zaměstnanec — uložit jako žádost o schválení
if ($user['role'] === 'zamestnanec') {
$vychozi_checkin = nastaveni('checkin_cas', '14:00');
$vychozi_checkout = nastaveni('checkout_cas', '10:00');
$vychozi = $typ === 'checkin' ? $vychozi_checkin : $vychozi_checkout;
// Zkontrolovat zda je čas nestandardní
$je_nestandardni = $cas !== $vychozi;
if ($je_nestandardni && !empty($input['zadost'])) {
// Uložit jako žádost — čeká na schválení manažera
db_query(
"UPDATE rezervace SET cas_zadost_typ=?, cas_zadost_hodnota=?, cas_zadost_stav='ceka', cas_zadost_user_id=? WHERE id=?",
[$typ, $cas, $user['id'], $id]
);
// Notifikovat manažera e-mailem
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_zadost_cas($id, $user, $typ, $cas);
} catch (\Throwable $e) { error_log($e->getMessage()); }
api_response(true, ['zadost' => true]);
} elseif ($je_nestandardni) {
// První volání — informovat frontend že je nestandardní
api_response(true, ['nestandardni' => true, 'vychozi' => $vychozi]);
}
// Standardní čas — uložit rovnou
}
// Admin/manažer nebo standardní čas — uložit přímo
$sloupec_cas = $typ === 'checkin' ? 'checkin_cas' : 'checkout_cas';
$sloupec_zmenil = $typ === 'checkin' ? 'checkin_zmenil_id' : 'checkout_zmenil_id';
db_query("UPDATE rezervace SET {$sloupec_cas}=?, {$sloupec_zmenil}=? WHERE id=?",
[$cas, $user['id'], $id]);
api_response(true, null);
}
// ------------------------------------------------------------
// SCHVÁLENÍ / ZAMÍTNUTÍ ŽÁDOSTI O ZMĚNU ČASU
// ------------------------------------------------------------
function rez_schvalit_cas(array $user, int $id, array $input): never {
if (!in_array($user['role'], ['admin','manazer'], true)) {
api_response(false, null, 'Pouze manažer může schvalovat.', 200);
}
$rez = db_row("SELECT * FROM rezervace WHERE id = ? AND cas_zadost_stav = 'ceka'", [$id]);
if (!$rez) api_response(false, null, 'Žádná čekající žádost.', 200);
$typ = $rez['cas_zadost_typ'];
$cas = $rez['cas_zadost_hodnota'];
$sloupec = $typ === 'checkin' ? 'checkin_cas' : 'checkout_cas';
$zmenil = $typ === 'checkin' ? 'checkin_zmenil_id' : 'checkout_zmenil_id';
db_query(
"UPDATE rezervace SET {$sloupec}=?, {$zmenil}=?, cas_zadost_stav='schvaleno' WHERE id=?",
[$cas, $user['id'], $id]
);
// E-mail zákazníkovi
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_schvaleni_cas($id, $typ, $cas);
} catch (\Throwable $e) { error_log($e->getMessage()); }
api_response(true, null);
}
function rez_zamitnout_cas(array $user, int $id, array $input): never {
if (!in_array($user['role'], ['admin','manazer'], true)) {
api_response(false, null, 'Pouze manažer může zamítat.', 200);
}
$rez = db_row("SELECT * FROM rezervace WHERE id = ? AND cas_zadost_stav = 'ceka'", [$id]);
if (!$rez) api_response(false, null, 'Žádná čekající žádost.', 200);
$poznamka = trim($input['poznamka'] ?? '');
db_query("UPDATE rezervace SET cas_zadost_stav='zamitnuto', cas_zadost_poznamka=? WHERE id=?",
[$poznamka ?: null, $id]);
api_response(true, null);
}
// ------------------------------------------------------------
// NÁVRH SLEVY
// ------------------------------------------------------------
function rez_navrhnout_slevu(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID', 400);
$rez = db_row('SELECT * FROM rezervace WHERE id = ?', [$id]);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 404);
if ($rez['stav'] === 'zrusena') api_response(false, null, 'Zrušenou rezervaci nelze upravit.', 400);
$castka = (float)($input['castka'] ?? 0);
$poznamka = trim($input['poznamka'] ?? '');
if ($castka <= 0) api_response(false, null, 'Výše slevy musí být kladná.', 400);
if (!$poznamka) api_response(false, null, 'Uveďte důvod slevy.', 400);
if (in_array($user['role'], ['admin', 'manazer'], true)) {
db_query("UPDATE rezervace SET sleva_castka=?, sleva_stav='schvalena', sleva_poznamka=?, sleva_schvalil_id=? WHERE id=?",
[$castka, $poznamka, $user['id'], $id]);
api_response(true, ['stav' => 'schvalena']);
}
db_query("UPDATE rezervace SET sleva_castka=?, sleva_stav='navrzena', sleva_poznamka=? WHERE id=?",
[$castka, $poznamka, $id]);
try { odeslat_navrh_slevy($id, $user, $castka, $poznamka); } catch (\Exception $e) { error_log($e->getMessage()); }
api_response(true, ['stav' => 'navrzena']);
}
// ------------------------------------------------------------
// SCHVÁLENÍ / ZAMÍTNUTÍ SLEVY
// ------------------------------------------------------------
function rez_rozhodnout_slevu(array $user, int $id, bool $schvalit, array $input): never {
auth_require_role($user, ['admin', 'manazer']);
if (!$id) api_response(false, null, 'Chybí ID', 400);
$rez = db_row("SELECT sleva_stav FROM rezervace WHERE id = ?", [$id]);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 404);
if ($rez['sleva_stav'] !== 'navrzena') {
api_response(false, null, 'Sleva není ve stavu čekající na schválení.', 400);
}
$novy_stav = $schvalit ? 'schvalena' : 'zamitnuta';
$poznamka = trim($input['poznamka'] ?? '');
db_query('UPDATE rezervace SET sleva_stav=?, sleva_schvalil_id=?, sleva_manazer_poznamka=? WHERE id=?',
[$novy_stav, $user['id'], $poznamka ?: null, $id]);
api_response(true, ['stav' => $novy_stav]);
}
// ------------------------------------------------------------
// PŘÍMÝ OVERRIDE CENY
// ------------------------------------------------------------
function rez_cena_override(array $user, int $id, array $input): never {
auth_require_role($user, ['admin', 'manazer']);
if (!$id) api_response(false, null, 'Chybí ID', 400);
$cena = isset($input['cena']) ? (float)$input['cena'] : null;
if ($cena !== null && $cena < 0) api_response(false, null, 'Cena nemůže být záporná.', 400);
db_query('UPDATE rezervace SET cena_upravena=? WHERE id=?', [$cena, $id]);
api_response(true, null);
}
// ------------------------------------------------------------
// DNEŠNÍ PŘÍJEZDY A ODJEZDY
// ------------------------------------------------------------
function rez_dnes(array $user): never {
$dnes = date('Y-m-d');
$prijezdy = db_rows(
"SELECT r.id, r.jmeno, r.prijmeni, r.pocet_hostu,
r.checkin_cas, r.poznamka, r.stav,
p.cislo AS pokoj_cislo,
COALESCE(p.nazev, CONCAT('Pokoj ', p.cislo)) AS pokoj_nazev
FROM rezervace r JOIN pokoje p ON p.id = r.pokoj_id
WHERE r.datum_prijezdu = ? AND r.stav != 'zrusena'
ORDER BY COALESCE(r.checkin_cas, '14:00') ASC",
[$dnes]
);
$odjezdy = db_rows(
"SELECT r.id, r.jmeno, r.prijmeni, r.pocet_hostu,
r.checkout_cas, r.stav,
p.cislo AS pokoj_cislo,
COALESCE(p.nazev, CONCAT('Pokoj ', p.cislo)) AS pokoj_nazev
FROM rezervace r JOIN pokoje p ON p.id = r.pokoj_id
WHERE r.datum_odjezdu = ? AND r.stav != 'zrusena'
ORDER BY COALESCE(r.checkout_cas, '10:00') ASC",
[$dnes]
);
$ubytovani = db_rows(
"SELECT r.id, r.jmeno, r.prijmeni, r.pocet_hostu,
r.datum_prijezdu, r.datum_odjezdu,
p.cislo AS pokoj_cislo,
COALESCE(p.nazev, CONCAT('Pokoj ', p.cislo)) AS pokoj_nazev
FROM rezervace r JOIN pokoje p ON p.id = r.pokoj_id
WHERE r.datum_prijezdu <= ? AND r.datum_odjezdu > ? AND r.stav != 'zrusena'
ORDER BY r.datum_odjezdu ASC",
[$dnes, $dnes]
);
api_response(true, ['datum' => $dnes, 'prijezdy' => $prijezdy,
'odjezdy' => $odjezdy, 'ubytovani' => $ubytovani]);
}
// ------------------------------------------------------------
// INTERNÍ HELPERY
// ------------------------------------------------------------
function _rez_validuj(array $input, ?array $user): array {
$typ_id = (int)($input['typ_id'] ?? 0);
$datum_od = trim($input['datum_prijezdu'] ?? '');
$datum_do = trim($input['datum_odjezdu'] ?? '');
$jmeno = trim($input['jmeno'] ?? '');
$prijmeni = trim($input['prijmeni'] ?? '');
$email = trim($input['email'] ?? '');
$telefon = trim($input['telefon'] ?? '');
$pocet_hostu = (int)($input['pocet_hostu'] ?? 1);
$poznamka = trim($input['poznamka'] ?? '');
$na_firmu = !empty($input['na_firmu']) ? 1 : 0;
$firma = trim($input['firma'] ?? '');
$ico = trim($input['ico'] ?? '');
$dic = trim($input['dic'] ?? '');
$faktura_ulice = trim($input['faktura_ulice'] ?? '');
$faktura_psc = trim($input['faktura_psc'] ?? '');
$faktura_mesto = trim($input['faktura_mesto'] ?? '');
$jazyk = in_array($input['jazyk'] ?? '', ['cs','en','de'], true) ? $input['jazyk'] : 'cs';
if (!$typ_id) api_response(false, null, 'Vyberte typ pokoje.', 400);
if (!$datum_od) api_response(false, null, 'Zadejte datum příjezdu.', 400);
if (!$datum_do) api_response(false, null, 'Zadejte datum odjezdu.', 400);
if (!$jmeno) api_response(false, null, 'Zadejte jméno hosta.', 400);
if (!$prijmeni) api_response(false, null, 'Zadejte příjmení hosta.', 400);
if (!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
api_response(false, null, 'Zadejte platný e-mail.', 400);
}
if (!$telefon) api_response(false, null, 'Zadejte telefonní číslo.', 400);
if ($datum_od >= $datum_do) {
api_response(false, null, 'Datum odjezdu musí být po datu příjezdu.', 400);
}
if ($pocet_hostu < 1) api_response(false, null, 'Počet hostů musí být alespoň 1.', 400);
if ($na_firmu && !$firma) {
api_response(false, null, 'Při objednávce na firmu zadejte název firmy.', 400);
}
$typ = db_row('SELECT id, kapacita, min_pobyt_noci FROM typy_pokoju WHERE id = ? AND aktivni = 1', [$typ_id]);
if (!$typ) api_response(false, null, 'Zvolený typ pokoje neexistuje.', 400);
if ($pocet_hostu > (int)$typ['kapacita']) {
api_response(false, null, 'Typ pokoje má kapacitu ' . $typ['kapacita'] . ' osob, zadali jste ' . $pocet_hostu . '.', 400);
}
$pocet_noci = _rez_pocet_noci($datum_od, $datum_do);
if ($pocet_noci < (int)$typ['min_pobyt_noci']) {
api_response(false, null, 'Minimální délka pobytu pro tento typ pokoje je ' . $typ['min_pobyt_noci'] . ' nocí.', 400);
}
return [
'typ_id' => $typ_id,
'pokoj_id' => 0,
'datum_prijezdu' => $datum_od,
'datum_odjezdu' => $datum_do,
'pocet_noci' => $pocet_noci,
'jmeno' => $jmeno,
'prijmeni' => $prijmeni,
'email' => $email,
'telefon' => $telefon,
'pocet_hostu' => $pocet_hostu,
'poznamka' => $poznamka ?: null,
'na_firmu' => $na_firmu,
'firma' => $firma ?: null,
'ico' => $ico ?: null,
'dic' => $dic ?: null,
'faktura_ulice' => $faktura_ulice ?: null,
'faktura_psc' => $faktura_psc ?: null,
'faktura_mesto' => $faktura_mesto ?: null,
'jazyk' => $jazyk,
];
}
function _rez_prirad_pokoj(int $typ_id, string $datum_od, string $datum_do, int $exclude_id = 0): int {
$pokoje = db_rows(
'SELECT id FROM pokoje WHERE typ_id = ? AND aktivni = 1 ORDER BY poradi ASC, cislo ASC',
[$typ_id]
);
foreach ($pokoje as $p) {
$params = [$p['id'], $datum_do, $datum_od];
$exclude_sql = '';
if ($exclude_id) { $exclude_sql = 'AND id != ?'; $params[] = $exclude_id; }
$konflikt = db_val(
"SELECT id FROM rezervace
WHERE pokoj_id = ? AND stav != 'zrusena'
AND datum_prijezdu < ? AND datum_odjezdu > ?
{$exclude_sql} LIMIT 1",
$params
);
$blokovano = db_val(
'SELECT id FROM blokovane_terminy WHERE pokoj_id = ? AND datum_od < ? AND datum_do > ? LIMIT 1',
[$p['id'], $datum_do, $datum_od]
);
if (!$konflikt && !$blokovano) return (int)$p['id'];
}
return 0;
}
function _rez_zkontroluj_dostupnost(int $pokoj_id, string $datum_od, string $datum_do, int $exclude_id = 0): void {
$params = [$datum_do, $datum_od, $pokoj_id];
$exclude_sql = '';
if ($exclude_id) { $exclude_sql = 'AND r.id != ?'; $params[] = $exclude_id; }
$konflikt = db_val(
"SELECT r.id FROM rezervace r
WHERE r.stav != 'zrusena'
AND r.datum_prijezdu < ? AND r.datum_odjezdu > ?
AND r.pokoj_id = ? {$exclude_sql} LIMIT 1",
$params
);
if ($konflikt) api_response(false, null, 'Zvolený pokoj je v tomto termínu obsazen.', 409);
$blokovano = db_val(
'SELECT id FROM blokovane_terminy WHERE pokoj_id = ? AND datum_od < ? AND datum_do > ? LIMIT 1',
[$pokoj_id, $datum_do, $datum_od]
);
if ($blokovano) api_response(false, null, 'Zvolený pokoj je v tomto termínu blokován.', 409);
}
function _rez_uloz_doplnky(int $rezervace_id, array $doplnky_ids, int $pocet_noci, int $pocet_hostu): void {
foreach ($doplnky_ids as $doplnek_id) {
$d = db_row('SELECT * FROM doplnky WHERE id = ? AND aktivni = 1', [(int)$doplnek_id]);
if (!$d) continue;
$noci_pro_vypocet = in_array($d['typ_uctovani'], ['za_noc', 'za_osobu_noc'], true) ? $pocet_noci : 1;
$hostu_pro_vypocet = $d['typ_uctovani'] === 'za_osobu_noc' ? $pocet_hostu : 1;
$cena_celkem = round($d['cena'] * $noci_pro_vypocet * $hostu_pro_vypocet, 2);
db_query(
'INSERT INTO rezervace_doplnky (rezervace_id, doplnek_id, nazev, cena, typ_uctovani, pocet_noci, cena_celkem)
VALUES (?, ?, ?, ?, ?, ?, ?)',
[$rezervace_id, $d['id'], $d['nazev'], $d['cena'], $d['typ_uctovani'],
$noci_pro_vypocet, $cena_celkem]
);
}
// Sjednotit cena_upravena hned teď, aby DB odpovídala zobrazené ceně
// (jinak by cena_upravena zůstala NULL a pozdější operace s doplňky
// by nesprávně počítaly "starou cenu" jen z cena_zaklad)
$suma_doplnku = (float)db_val('SELECT COALESCE(SUM(cena_celkem),0) FROM rezervace_doplnky WHERE rezervace_id = ?', [$rezervace_id]);
if ($suma_doplnku > 0) {
$cena_zaklad = (float)db_val('SELECT cena_zaklad FROM rezervace WHERE id = ?', [$rezervace_id]);
db_query('UPDATE rezervace SET cena_upravena = ? WHERE id = ?', [$cena_zaklad + $suma_doplnku, $rezervace_id]);
}
}
function _rez_upsert_zakaznik(array $data): void {
db_query(
'INSERT INTO zakaznici (jmeno, prijmeni, email, telefon, firma, ico, dic, faktura_ulice, faktura_psc, faktura_mesto)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
jmeno = VALUES(jmeno),
prijmeni = VALUES(prijmeni),
telefon = COALESCE(VALUES(telefon), telefon),
firma = COALESCE(VALUES(firma), firma),
ico = COALESCE(VALUES(ico), ico),
dic = COALESCE(VALUES(dic), dic),
faktura_ulice = COALESCE(VALUES(faktura_ulice), faktura_ulice),
faktura_psc = COALESCE(VALUES(faktura_psc), faktura_psc),
faktura_mesto = COALESCE(VALUES(faktura_mesto), faktura_mesto)',
[
$data['jmeno'], $data['prijmeni'], $data['email'], $data['telefon'],
$data['firma'] ?? null, $data['ico'] ?? null, $data['dic'] ?? null,
$data['faktura_ulice'] ?? null, $data['faktura_psc'] ?? null, $data['faktura_mesto'] ?? null,
]
);
}
function _rez_pocet_noci(string $od, string $do): int {
return max(1, (int)(new DateTime($od))->diff(new DateTime($do))->days);
}
// ============================================================
// POTVRZENÍ REZERVACE
// ============================================================
function rez_potvrdit(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID', 200);
if (!in_array($user['role'], ['admin', 'manazer'], true) && !auth_has_opravneni($user, 'potvrzeni_rezervace')) {
api_response(false, null, 'Nemáte oprávnění potvrzovat rezervace.', 200);
}
$rez = db_row(
"SELECT r.stav, r.pocet_noci, r.cena_zaklad, r.cena_upravena, p.typ_id
FROM rezervace r
JOIN pokoje p ON p.id = r.pokoj_id
WHERE r.id = ?",
[$id]
);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 200);
if ($rez['stav'] !== 'ceka') api_response(false, null, 'Rezervace není ve stavu Čeká.', 200);
// Přiřadit pokoj pokud byl vybrán
$pokoj_id = (int)($input['pokoj_id'] ?? 0);
if ($pokoj_id) {
$pokoj = db_row('SELECT id, typ_id FROM pokoje WHERE id = ? AND aktivni = 1', [$pokoj_id]);
if (!$pokoj) api_response(false, null, 'Pokoj nenalezen', 200);
// Pokud zaměstnanec vybírá pokoj jiného (dražšího) typu — vyžádat schválení manažera
if ($user['role'] === 'zamestnanec' && (int)$pokoj['typ_id'] !== (int)$rez['typ_id']) {
$stara_cena = $rez['cena_upravena'] !== null ? (float)$rez['cena_upravena'] : (float)$rez['cena_zaklad'];
$cena_za_noc_novy_typ = (float)db_val('SELECT cena_za_noc FROM typy_pokoju WHERE id = ?', [$pokoj['typ_id']]);
$spravna_cena_typu = round($cena_za_noc_novy_typ * (int)$rez['pocet_noci'], 2);
if ($spravna_cena_typu > $stara_cena + 0.01) {
db_query(
"UPDATE rezervace SET
pokoj_zadost_pokoj_id = ?, pokoj_zadost_cena_typu = ?,
pokoj_zadost_stav = 'ceka', pokoj_zadost_user_id = ?
WHERE id = ?",
[$pokoj_id, $spravna_cena_typu, $user['id'], $id]
);
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_zadost_zmena_pokoje($id, $user, $pokoj_id, $stara_cena, $spravna_cena_typu);
} catch (\Throwable $e) {
error_log('[Mailer] Chyba při odesílání žádosti o pokoj: ' . $e->getMessage());
}
api_response(false, null,
'Vybraný pokoj je dražšího typu — žádost o schválení byla odeslána manažerovi. ' .
'Rezervaci potvrďte až po schválení, nebo zvolte pokoj odpovídajícího typu.',
200
);
}
}
db_query('UPDATE rezervace SET pokoj_id = ?, stav = ? WHERE id = ?', [$pokoj_id, 'potvrzena', $id]);
} else {
db_query('UPDATE rezervace SET stav = ? WHERE id = ?', ['potvrzena', $id]);
}
// Odeslat potvrzovací e-mail zákazníkovi
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_potvrzeni_potvrzeno($id);
} catch (\Throwable $e) {
error_log('[Mailer] Chyba při odesílání potvrzení: ' . $e->getMessage());
}
api_response(true, null);
}
// ============================================================
// ODEBRÁNÍ DOPLŇKU Z REZERVACE
// ============================================================
function rez_odebrat_doplnek(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID rezervace', 200);
if (!auth_has_opravneni($user, 'zmena_rezervace') && !in_array($user['role'], ['admin','manazer'], true)) {
api_response(false, null, 'Nedostatečná oprávnění', 200);
}
$nazev = trim($input['nazev'] ?? '');
if (!$nazev) api_response(false, null, 'Chybí název doplňku', 200);
// Najít a smazat doplněk
$dp = db_row('SELECT id, cena_celkem FROM rezervace_doplnky WHERE rezervace_id = ? AND nazev = ? LIMIT 1', [$id, $nazev]);
if (!$dp) api_response(false, null, 'Doplněk nenalezen', 200);
$rez_pred = db_row('SELECT cena_zaklad, cena_upravena FROM rezervace WHERE id = ?', [$id]);
$stara_cena_dp_suma = (float)db_val('SELECT COALESCE(SUM(cena_celkem),0) FROM rezervace_doplnky WHERE rezervace_id = ?', [$id]);
$stara_cena = $rez_pred['cena_upravena'] !== null
? (float)$rez_pred['cena_upravena']
: (float)$rez_pred['cena_zaklad'] + $stara_cena_dp_suma;
db_query('DELETE FROM rezervace_doplnky WHERE id = ?', [$dp['id']]);
// Přepočítat cenu rezervace
$nova_cena_dp = db_val('SELECT COALESCE(SUM(cena_celkem),0) FROM rezervace_doplnky WHERE rezervace_id = ?', [$id]);
$cena_zaklad = db_val('SELECT cena_zaklad FROM rezervace WHERE id = ?', [$id]);
$nova_cena = (float)$cena_zaklad + (float)$nova_cena_dp;
db_query('UPDATE rezervace SET cena_upravena = ? WHERE id = ?', [$nova_cena, $id]);
if (abs($nova_cena - $stara_cena) >= 0.01) {
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_zmenu_ceny_pokoje($id, $stara_cena, $nova_cena, 'duvod_doplnek_odebran', $nazev, 'odebrana', (float)$dp['cena_celkem']);
} catch (\Throwable $e) {
error_log('[Mailer] Chyba při odesílání změny ceny (odebrání doplňku): ' . $e->getMessage());
}
}
api_response(true, null);
}
// ============================================================
// PŘIDÁNÍ DOPLŇKU K REZERVACI
// ============================================================
function rez_pridat_doplnek(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID rezervace', 200);
if (!auth_has_opravneni($user, 'zmena_rezervace') && !in_array($user['role'], ['admin','manazer'], true)) {
api_response(false, null, 'Nedostatečná oprávnění', 200);
}
$doplnek_id = (int)($input['doplnek_id'] ?? 0);
$nazev = trim($input['nazev'] ?? '');
$cena = (float)($input['cena'] ?? 0);
$typ = $input['typ_uctovani'] ?? 'jednorazove';
$cena_celkem = (float)($input['cena_celkem'] ?? $cena);
if (!$doplnek_id || !$nazev) api_response(false, null, 'Chybí údaje doplňku', 200);
$rez = db_row('SELECT pocet_noci, pocet_hostu, cena_zaklad, cena_upravena FROM rezervace WHERE id = ?', [$id]);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 200);
$stara_cena_dp_suma = (float)db_val('SELECT COALESCE(SUM(cena_celkem),0) FROM rezervace_doplnky WHERE rezervace_id = ?', [$id]);
$stara_cena = $rez['cena_upravena'] !== null
? (float)$rez['cena_upravena']
: (float)$rez['cena_zaklad'] + $stara_cena_dp_suma;
$pocet_noci = in_array($typ, ['za_noc', 'za_osobu_noc'], true) ? (int)$rez['pocet_noci'] : 1;
$multiplikator_hostu = $typ === 'za_osobu_noc' ? (int)$rez['pocet_hostu'] : 1;
$celkem = $cena * $pocet_noci * $multiplikator_hostu;
db_query(
'INSERT INTO rezervace_doplnky (rezervace_id, doplnek_id, nazev, cena, typ_uctovani, pocet_noci, cena_celkem)
VALUES (?, ?, ?, ?, ?, ?, ?)',
[$id, $doplnek_id, $nazev, $cena, $typ, $pocet_noci, $celkem]
);
// Přepočítat cenu
$nova_cena_dp = db_val('SELECT COALESCE(SUM(cena_celkem),0) FROM rezervace_doplnky WHERE rezervace_id = ?', [$id]);
$cena_zaklad = db_val('SELECT cena_zaklad FROM rezervace WHERE id = ?', [$id]);
$nova_cena = (float)$cena_zaklad + (float)$nova_cena_dp;
db_query('UPDATE rezervace SET cena_upravena = ? WHERE id = ?', [$nova_cena, $id]);
if (abs($nova_cena - $stara_cena) >= 0.01) {
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_zmenu_ceny_pokoje($id, $stara_cena, $nova_cena, 'duvod_doplnek_pridan', $nazev, 'pridana', $celkem);
} catch (\Throwable $e) {
error_log('[Mailer] Chyba při odesílání změny ceny (přidání doplňku): ' . $e->getMessage());
}
}
api_response(true, null);
}
// ============================================================
// ÚPRAVA ÚDAJŮ HOSTA
// ============================================================
function rez_upravit_hosta(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID', 200);
if (!auth_has_opravneni($user, 'zmena_rezervace') && !in_array($user['role'], ['admin','manazer'], true)) {
api_response(false, null, 'Nedostatečná oprávnění', 200);
}
$rez = db_row('SELECT id FROM rezervace WHERE id = ?', [$id]);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 200);
$jmeno = trim($input['jmeno'] ?? '');
$prijmeni = trim($input['prijmeni'] ?? '');
$email = trim($input['email'] ?? '');
if (!$jmeno || !$prijmeni) api_response(false, null, 'Jméno a příjmení jsou povinné.', 200);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) api_response(false, null, 'Neplatný e-mail.', 200);
$na_firmu = !empty($input['na_firmu']) ? 1 : 0;
$firma = trim($input['firma'] ?? '');
// Validace - pokud na firmu, musí být název
if ($na_firmu && !$firma) {
api_response(false, null, 'Při fakturaci na firmu zadejte název firmy.', 200);
}
db_query(
'UPDATE rezervace SET jmeno=?, prijmeni=?, email=?, telefon=?,
poznamka=?, faktura_ulice=?, faktura_psc=?, faktura_mesto=?,
na_firmu=?, firma=?, ico=?, dic=?
WHERE id=?',
[
$jmeno, $prijmeni, $email,
trim($input['telefon'] ?? ''),
trim($input['poznamka'] ?? ''),
trim($input['faktura_ulice'] ?? ''),
trim($input['faktura_psc'] ?? ''),
trim($input['faktura_mesto'] ?? ''),
$na_firmu,
$firma,
trim($input['ico'] ?? ''),
trim($input['dic'] ?? ''),
$id,
]
);
api_response(true, null);
}
// ============================================================
// ZMĚNA PŘIŘAZENÉHO POKOJE
// ============================================================
function rez_zmenit_pokoj(array $user, int $id, array $input): never {
if (!$id) api_response(false, null, 'Chybí ID', 200);
if (!in_array($user['role'], ['admin', 'manazer'], true) && !auth_has_opravneni($user, 'zmena_terminu')) {
api_response(false, null, 'Nemáte oprávnění měnit pokoj.', 200);
}
$rez = db_row(
"SELECT r.pokoj_id, r.pocet_noci, r.cena_zaklad, r.cena_upravena, p.typ_id, r.stav
FROM rezervace r
JOIN pokoje p ON p.id = r.pokoj_id
WHERE r.id = ?",
[$id]
);
if (!$rez) api_response(false, null, 'Rezervace nenalezena', 200);
if ($rez['stav'] === 'zrusena') api_response(false, null, 'Zrušenou rezervaci nelze měnit.', 200);
$novy_pokoj_id = (int)($input['pokoj_id'] ?? 0);
if (!$novy_pokoj_id) api_response(false, null, 'Chybí ID nového pokoje.', 200);
$pokoj = db_row('SELECT id, typ_id FROM pokoje WHERE id = ? AND aktivni = 1', [$novy_pokoj_id]);
if (!$pokoj) api_response(false, null, 'Pokoj nenalezen.', 200);
$stara_cena = $rez['cena_upravena'] !== null ? (float)$rez['cena_upravena'] : (float)$rez['cena_zaklad'];
// Skutečná cena odpovídající novému typu pokoje (pro kontrolu neoprávněné slevy)
$cena_za_noc_novy_typ = (float)db_val('SELECT cena_za_noc FROM typy_pokoju WHERE id = ?', [$pokoj['typ_id']]);
$spravna_cena_typu = round($cena_za_noc_novy_typ * (int)$rez['pocet_noci'], 2);
$nova_cena_vstup = $input['nova_cena'] ?? null;
$cena_zmenena = false;
$nova_cena = $stara_cena;
// Zaměstnanec ponechává starou (nižší) cenu, ačkoliv nový typ je dražší — vyžaduje schválení
if (
$user['role'] === 'zamestnanec'
&& $nova_cena_vstup === null
&& $spravna_cena_typu > $stara_cena + 0.01
) {
db_query(
"UPDATE rezervace SET
pokoj_zadost_pokoj_id = ?, pokoj_zadost_cena_typu = ?,
pokoj_zadost_stav = 'ceka', pokoj_zadost_user_id = ?
WHERE id = ?",
[$novy_pokoj_id, $spravna_cena_typu, $user['id'], $id]
);
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_zadost_zmena_pokoje($id, $user, $novy_pokoj_id, $stara_cena, $spravna_cena_typu);
} catch (\Throwable $e) {
error_log('[Mailer] Chyba při odesílání žádosti o pokoj: ' . $e->getMessage());
}
api_response(true, ['zadost' => true]);
}
if ($nova_cena_vstup !== null) {
$nova_cena = round((float)$nova_cena_vstup, 2);
db_query('UPDATE rezervace SET pokoj_id = ?, cena_zaklad = ?, cena_upravena = NULL WHERE id = ?',
[$novy_pokoj_id, $nova_cena, $id]);
$cena_zmenena = abs($nova_cena - $stara_cena) >= 0.01;
} else {
db_query('UPDATE rezervace SET pokoj_id = ? WHERE id = ?', [$novy_pokoj_id, $id]);
}
// Notifikovat zákazníka pouze pokud se cena skutečně změnila
if ($cena_zmenena) {
try {
require_once __DIR__ . '/../includes/mailer.php';
odeslat_zmenu_ceny_pokoje($id, $stara_cena, $nova_cena);
} catch (\Throwable $e) {
error_log('[Mailer] Chyba při odesílání změny ceny: ' . $e->getMessage());
}
}
api_response(true, null);
}
// ------------------------------------------------------------
// SCHVÁLENÍ / ZAMÍTNUTÍ ŽÁDOSTI O ZMĚNU POKOJE SE SLEVOU
// ------------------------------------------------------------
function rez_schvalit_pokoj(array $user, int $id): never {
if (!in_array($user['role'], ['admin','manazer'], true)) {
api_response(false, null, 'Pouze manažer může schvalovat.', 200);
}
$rez = db_row(
"SELECT pokoj_zadost_pokoj_id, pokoj_zadost_cena_typu, cena_zaklad, cena_upravena
FROM rezervace WHERE id = ? AND pokoj_zadost_stav = 'ceka'",
[$id]
);
if (!$rez) api_response(false, null, 'Žádná čekající žádost.', 200);
$stara_cena = $rez['cena_upravena'] !== null ? (float)$rez['cena_upravena'] : (float)$rez['cena_zaklad'];
$nova_pokoj_id = (int)$rez['pokoj_zadost_pokoj_id'];
db_query(
"UPDATE rezervace SET pokoj_id = ?, pokoj_zadost_stav = 'schvaleno' WHERE id = ?",
[$nova_pokoj_id, $id]
);
api_response(true, null);
}
function rez_zamitnout_pokoj(array $user, int $id, array $input): never {
if (!in_array($user['role'], ['admin','manazer'], true)) {
api_response(false, null, 'Pouze manažer může zamítat.', 200);
}
$rez = db_row("SELECT pokoj_zadost_user_id FROM rezervace WHERE id = ? AND pokoj_zadost_stav = 'ceka'", [$id]);
if (!$rez) api_response(false, null, 'Žádná čekající žádost.', 200);
$poznamka = trim($input['poznamka'] ?? '');
db_query("UPDATE rezervace SET pokoj_zadost_stav = 'zamitnuto', pokoj_zadost_poznamka = ? WHERE id = ?",
[$poznamka ?: null, $id]);
api_response(true, null);
}