'POST']); $form->field('username', ['required'=>true, 'label'=>'Jméno']); $form->field('password', ['type'=>'password', 'required'=>true, 'label'=>'Heslo']); $form->field('_login', ['type'=>'submit', 'label'=>'Přihlásit se']); if ($req->getMethod()=='POST') { $form->fill($req->getParsedBody()); if ($form->validate()) { $uz = $rows->one('users', ['username'=>$form->values['username'], 'is_active'=>1]); if (!$uz) { $form->error('username', 'Uživatel nenalezen'); } elseif (password_verify($form->values['password'], $uz['password'])) { unset($uz['password']); $_SESSION['user'] = $uz; return redirect('/'); } else { $form->error('password', 'Špatné heslo.'); } } } return render('form', ['form'=>$form]); }); route('', '/logout/', function ($req){ unset($_SESSION['user']); unset($_SESSION['flashes']); return redirect('/'); }); route('', '/zmena-hesla/', function ($req){ if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $form = new form(['method'=>'post']); $form->field('password_current', ['required'=>true, 'type'=>'password', 'label'=>'Stávající heslo']); $form->field('password', ['required'=>true, 'type'=>'password', 'label'=>'Nové heslo']); $form->field('password_again', ['required'=>true, 'type'=>'password', 'label'=>'Nové heslo znovu']); $form->field('_sbt', ['label'=>'Změnit heslo', 'type'=>'submit']); $form->rule('password_again', function ($v, $o){ return $v==$o['password']; }, 'Hesla se neshodují!'); $uz = $rows->one('users', $user['id']); $form->rule('password_current', function ($v, $o) use ($uz) { return password_verify($v, $uz['password']); }, 'Špatné zadané současné heslo!'); if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) { $rows->update('users', [ 'password'=>password_hash($form->values['password'], PASSWORD_DEFAULT) ], [ 'id'=>$user['id'] ]); flash('Heslo změněno.'); return redirect('/'); } return render('form', ['form'=>$form, 'title'=>'Změnit heslo']); }); // SKLAD route('GET', '/sklad/', function ($req){ if (!user()) return redirect('/login/'); /** @var severak\database\rows $rows */ $rows = di('rows'); $items = $rows->page('items', ['is_active'=>1], ['ord'=>'asc']); return render('items', ['items'=>$items]); }); $singletons['nabidka_form'] = function (){ $form = new severak\forms\form(['method'=>'POST']); $form->field('name', ['required'=>true, 'label'=>'Název']); $form->field('price', ['type'=>'number', 'label'=>'Cena']); $form->field('note', ['type'=>'textarea', 'label'=>'Poznámka']); $form->field('ord', ['type'=>'number', 'label'=>'Pořadí']); $form->field('is_amount_tracked', ['type'=>'checkbox', 'label'=>'Hlídat počet na skladě?']); $form->field('amount', ['type'=>'number', 'label'=>'Počet na skladě']); $form->field('_save', ['type'=>'submit', 'label'=>'Přidat']); $form->rule('price', function ($f){ return $f > 0 || $f < 0; }, 'Cena nemůže být nulová.'); return $form; }; route('', '/sklad/pridat/', function ($req){ if (!user()) return redirect('/login/'); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); /** @var severak\forms\form $form */ $form = di('nabidka_form'); if ($req->getMethod()=='POST') { $form->fill($req->getParsedBody()); if ($form->validate()) { $rows->insert('items', [ 'name'=>$form->values['name'], 'price'=>$form->values['price'], 'note'=>$form->values['note'], 'ord'=>$form->values['ord'], 'amount'=>$form->values['amount'], 'is_amount_tracked'=>$form->values['is_amount_tracked'], ]); return redirect('/sklad/'); } } return render('form', ['form'=>$form, 'title'=>'Přidat položku']); }); route('', '/sklad/upravit/{id}/', function ($req, $params){ if (!user()) return redirect('/login/'); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); /** @var severak\forms\form $form */ $form = di('nabidka_form'); $item = $rows->one('items', $params['id']); if (!$item) return notFound(); $form->fill($item); if ($req->getMethod()=='POST') { $form->fill($req->getParsedBody()); if ($form->validate()) { $rows->update('items', [ 'name'=>$form->values['name'], 'price'=>$form->values['price'], 'note'=>$form->values['note'], 'ord'=>$form->values['ord'], 'amount'=>$form->values['amount'], 'is_amount_tracked'=>$form->values['is_amount_tracked'], ], $params['id']); return redirect('/sklad/'); } } return render('form', ['form'=>$form, 'title'=>'Upravit položku']); }); // TODO - tohle nechceme přes GET route('', '/sklad/smazat/{id}/', function ($req, $params){ if (!user()) return redirect('/login/'); /** @var severak\database\rows $rows */ $rows = di('rows'); $rows->update('items', ['is_active'=>0], ['id'=>$params['id'] ]); return redirect('/sklad/'); }); // ČLENOVÉ route('', '/clenove/', function ($req){ if (!user()) return redirect('/login/'); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); if ($_POST['qrcode']) { $card = $rows->one('cards', ['id'=>$_POST['qrcode']]); if ($card) { return redirect('/clenove/detail/'. $card['member_id'] . '/'); } else { flash('Karta není registrována.', 'error'); return redirect('/clenove/'); } } $searchFor = $_GET['searchFor'] ?? null; $page = $_GET['page'] ?? 1; if ($searchFor) { $searchSql = '%' . $searchFor . '%'; $members = $rows->more('members', $rows->fragment('name LIKE ? OR email LIKE ? OR phone LIKE ?', [$searchSql, $searchSql, $searchSql])); $pages = 1; } else { $members = $rows->page('members', [], ['name'=>'asc'], $page, 30); $pages = $rows->pages; } return render('members', ['members'=>$members, 'page'=>$page, 'pages'=>$pages, 'searchFor'=>$searchFor]); }); function items_sold(rows $rows, $od, $do) { $tsOd = strtotime($od); $tsDo = strtotime($do); return $rows->execute($rows->query('SELECT item_id, SUM(amount) AS amount FROM sold_items WHERE date>? AND datefetchAll(PDO::FETCH_KEY_PAIR); } route('', '/sklad/prodano/', function ($req){ if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $this_week = items_sold($rows, 'monday this week', 'now'); $last_week = items_sold($rows, 'monday last week', 'sunday last week +24 hours -1 sec'); $this_month = items_sold($rows, 'first day of this month midnight', 'last day of this month midnight +24 hours -1 sec'); $last_month = items_sold($rows, 'first day of last month midnight', 'last day of last month midnight +24 hours -1 sec'); $items = $rows->page('items', ['is_active'=>1, 'is_amount_tracked'=>1], ['ord'=>'asc']); return render('items_sold', ['items'=>$items, 'this_week'=>$this_week, 'last_week'=>$last_week, 'this_month'=>$this_month, 'last_month'=>$last_month]); }); route('', '/clenove/pridat/', function ($req){ if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $form = new severak\forms\form(['method'=>'POST']); $form->field('card_id', ['required'=>true, 'type'=>'number', 'label'=>'Číslo karty', 'id'=>'qrcode']); $form->field('name', ['required'=>true, 'label'=>'Jméno']); $form->field('email', ['type'=>'email', 'label'=>'E-mail']); $form->field('phone', ['type'=>'phone', 'label'=>'Telefon']); $form->field('date_of_birth', ['type'=>'date', 'label'=>'Datum narození']); $form->field('_save', ['type'=>'submit', 'label'=>'Přidat']); if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) { $card = $rows->one('cards', $form->values['card_id']); if ($card) { $form->error('card_id', 'Karta již je registrovaná v systému!'); } // TODO - tyhle duplikáty řešit jinak if ($rows->one('members', ['name'=>$form->values['name']])) { $form->error('name', 'Tento člen již kartičku má!'); } if (!empty($form->values['email']) && $rows->one('members', ['email'=>$form->values['email']])) { $form->error('email', 'Tento email již má některý člen.'); } if (!empty($form->values['phone']) && $rows->one('members', ['phone'=>$form->values['phone']])) { $form->error('phone', 'Tento telefon již má některý člen.!'); } if ($form->isValid) { $memberId = $rows->insert('members', [ 'name'=>$form->values['name'], 'email'=>$form->values['email'], 'phone'=>$form->values['phone'], 'date_of_birth'=>$form->values['date_of_birth'], ]); $rows->insert('cards', [ 'id'=>$form->values['card_id'], 'member_id'=>$memberId, 'issued_by'=>$user['id'], 'issued_at'=>time(), 'is_active'=>1 ]); flash('Člen byl úspěšně registrován.'); return redirect('/'); } } return render('form', ['form'=>$form, 'title'=>'Přidat člena']); }); route('', '/clenove/detail/{id}/', function ($req, $params) { if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $member = $rows->one('members', $params['id']); if (!$member) return notFound(); $page = $_GET['page'] ?? 1; $transactions = $rows->page('transactions', ['member_id'=>$params['id']], ['issued_at'=>'desc'], $page, 30); $cards = $rows->more('cards', ['member_id'=>$params['id']], ['issued_at'=>'desc']); $pages = $rows->pages; return render('member_detail', ['member'=>$member, 'page'=>$page, 'pages'=>$pages, 'transactions'=>$transactions, 'cards'=>$cards]); }); route('', '/clenove/upravit/{id}/', function ($req, $params) { if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $member = $rows->one('members', $params['id']); if (!$member) return notFound(); $form = new severak\forms\form(['method'=>'POST']); $form->field('name', ['required'=>true, 'label'=>'Jméno']); $form->field('email', ['type'=>'email', 'label'=>'E-mail']); $form->field('phone', ['type'=>'phone', 'label'=>'Telefon']); $form->field('date_of_birth', ['type'=>'date', 'label'=>'Datum narození']); $form->field('note', ['type'=>'textarea', 'rows'=>3, 'label'=>'Poznámka']); $form->field('is_active', ['type'=>'checkbox', 'label'=>'Je aktivní?']); $form->field('_save', ['type'=>'submit', 'label'=>'Upravit']); $form->fill($member); if ($req->getMethod()=='POST') { $form->fill($req->getParsedBody()); // TODO - zde nějak ošetřovat duplicity if ($form->validate()) { $rows->update('members', [ 'name'=>$form->values['name'], 'email'=>$form->values['email'], 'phone'=>$form->values['phone'], 'date_of_birth'=>$form->values['date_of_birth'], 'note'=>$form->values['note'], 'is_active'=>$form->values['is_active'] ?? 0, ], $params['id']); if (!$form->values['is_active']) { // deaktivujeme kartičku $rows->update('cards', ['is_active'=>0, 'note'=>'deaktivována s uživatelem'], ['is_active'=>'1', 'member_id'=>$params['id']]); } if (!$member['is_active'] && $form->values['is_active']) { flash('Nyní musíte vystavit novou kartičku.', 'warning'); } return redirect('/clenove/detail/'. $params['id'].'/'); } } return render('form', ['form'=>$form, 'title'=>'Upravit člena']); }); route('', '/clenove/nova_karta/{id}/', function ($req, $params) { if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $member = $rows->one('members', $params['id']); if (!$member) return notFound(); $reasons = [ 'ztracená' => 'karta byla ztracená', 'ukradená' => 'karta byla ukradená', 'obnovení členství' => 'obnovení členství' ]; $form = new severak\forms\form(['method'=>'POST']); $form->field('card_id', ['required'=>true, 'type'=>'number', 'label'=>'Číslo karty', 'id'=>'qrcode']); $form->field('reason', ['type'=>'select', 'label'=>'Důvod vydání nové karty', 'options'=>$reasons]); $form->field('block_original', ['type'=>'checkbox', 'label'=>'zablokovat původní kartu']); $form->field('_save', ['type'=>'submit', 'label'=>'Vystavit novou kartu']); if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) { $card = $rows->one('cards', $form->values['card_id']); if ($card) { $form->error('card_id', 'Karta již je registrovaná v systému!'); } $form->fill($req->getParsedBody()); if ($form->validate()) { // deaktivujeme původní kartu $rows->update('cards', [ 'is_active' => 0, 'is_blocked' => $form->values['block_original'] ?? 0, 'note' => $form->values['reason'] ], ['is_active' => '1', 'member_id' => $params['id']]); // přidáváme novou $rows->insert('cards', [ 'id'=>$form->values['card_id'], 'member_id'=>$params['id'], 'issued_by'=>$user['id'], 'issued_at'=>time(), 'is_active'=>1 ]); return redirect('/clenove/detail/'. $params['id'].'/'); } } return render('form', ['form'=>$form, 'title'=>'Nová karta']); }); // POKLADNA: route('','/pokladna/', function(){ return render('pokladna', ['title'=>'pokladna']); }); route('', '/pokladna/dobit/', function ($req){ if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $form = new form(['method'=>'post']); $form->field('card_id', ['required'=>true, 'type'=>'number', 'label'=>'Číslo karty', 'id'=>'qrcode']); $form->field('amount', ['required'=>true, 'type'=>'number', 'label'=>'Částka']); $form->field('_sbt', ['label'=>'Vložit', 'type'=>'submit']); // TODO - zde kontrolovat maxmální a minimální výši nabití if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) { $card = $rows->one('cards', ['id'=>$form->values['card_id']]); if (!$card || !$card['is_active']) { $form->error('card_id', 'Neznámá/neplatná karta!'); } if ($card && $card['is_blocked']) { $form->error('card_id', 'Karta je zablokovaná.'); } if ($card) { $member = $rows->one('members', $card['member_id']); } if ($form->isValid) { // BIG TODO - tohle dělat v databázové transakci $rows->insert('transactions', [ 'member_id' => $member['id'], 'card_id' => $card['id'], 'issued_by'=>$user['id'], 'issued_at'=>time(), 'amount'=>$form->values['amount'], 'is_cash'=>1 ]); $rows->execute($rows->query('UPDATE members SET balance = balance + ? WHERE id=?', [$form->values['amount'], $member['id']])); flash('Kredit úspěšně dobit!', 'success'); return redirect('/'); } } return render('form', ['form'=>$form, 'title'=>'Dobít kartu']); }); // TODO - zůstatek, vybrat // BAR: route('GET', '/bar/', function ($req){ if (!user()) return redirect('/login/'); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $nabidka = $rows->more('items', ['is_active'=>1], ['ord'=>'asc']); return render('bar', ['items'=>$nabidka]); }); route('POST', '/bar/userinfo/', function ($req){ if (!user()) return jsonResponse(['error'=>'Unauthorized.'], 403); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $Q = $req->getParsedBody(); if (empty($Q['card_id'])) { return jsonResponse(['error'=>'Špatný formát čísla karty.']); } $card = $rows->one('cards', $Q['card_id']); if ($card && $card['is_blocked']) { return jsonResponse(['error'=>'Karta je zablokovaná.']); } if (!$card || !$card['is_active']) { return jsonResponse(['error'=>'Karta není aktivní.']); } $member = $rows->one('members', $card['member_id']); if ($member['balance']==0) { return jsonResponse(['error'=>'Karta není nabitá.']); } $dobMember = date_create($member['date_of_birth']); $before18Years = date_create('now - 18 years'); $canBuyAlcohol = $dobMember && ($dobMember < $before18Years); return jsonResponse([ 'name' => $member['name'], 'balance' => $member['balance'], 'can_buy_alcohol' => $canBuyAlcohol, ]); }); route('POST', '/bar/buy/', function ($req){ if (!user()) return jsonResponse(['error'=>'Vypršelo přihlášení.']); $user = user(); /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $Q = $req->getParsedBody(); if (empty($Q['card_id'])) { return jsonResponse(['error'=>'Špatný formát čísla karty.']); } $card = $rows->one('cards', $Q['card_id']); if ($card && $card['is_blocked']) { return jsonResponse(['error'=>'Karta je zablokovaná.']); } if (!$card || !$card['is_active']) { return jsonResponse(['error'=>'Karta není aktivní.']); } $member = $rows->one('members', $card['member_id']); if ($member['balance']<1) { return jsonResponse(['error'=>'Karta není nabitá.']); } $totalSum = 0; foreach ($Q['items'] as $item) { $totalSum = $totalSum + ($item['price'] * $item['amount']); } if ($member['balance']<$totalSum) { return jsonResponse(['error'=>'Na kartě není dostatek peněz.', 'balance'=>$member['balance']]); } $transcactionId = $rows->insert('transactions', [ 'member_id' => $member['id'], 'card_id' => $card['id'], 'issued_by'=>$user['id'], 'issued_at'=>time(), 'amount'=>$totalSum * -1, 'items' => json_encode($Q['items']), 'is_cash'=>0 ]); $rows->execute($rows->query('UPDATE members SET balance = balance - ? WHERE id=?', [$totalSum, $member['id']])); $isAmountTracked = array_column($rows->more('items'), 'is_amount_tracked', 'id'); foreach ($Q['items'] as $item) { if ($item['id'] && $isAmountTracked[$item['id']]) { $rows->insert('sold_items', [ 'item_id' => $item['id'], 'transaction_id' => $transcactionId, 'amount' => $item['amount'], 'date'=>time() ]); $rows->execute($rows->query('UPDATE items SET amount=amount-1 WHERE id=?', [$item['id']])); } } return jsonResponse(['success'=>true]); }); // OBSLUHA route('GET', '/obsluha/', function ($req){ if (!user()) return redirect('/login/'); /** @var severak\database\rows $rows */ $rows = di('rows'); $items = $rows->page('users', [], ['is_active'=>'desc', 'name'=>'asc']); return render('users', ['users'=>$items]); }); route('', '/obsluha/pridat/', function ($req){ if (!user()) return redirect('/login/'); $user = user(); if (!$user['is_superuser']) { flash('Obsluhu může přidávat jen admin.', 'warning'); return redirect('/'); } /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $form = new form(['method'=>'post']); $form->field('username', ['label'=>'Uživatelské jméno']); $form->field('password', ['required'=>true, 'type'=>'password', 'label'=>'Heslo']); $form->field('password_again', ['required'=>true, 'type'=>'password', 'label'=>'Heslo znovu']); $form->field('name', ['required'=>true, 'type'=>'text', 'label'=>'Jméno']); $form->field('card_id', ['type'=>'number', 'label'=>'Číslo členské karty', 'id'=>'qrcode']); $form->field('_sbt', ['label'=>'Přidat', 'type'=>'submit']); $form->rule('password_again', function ($v, $o){ return $v==$o['password']; }, 'Hesla se neshodují!'); if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody()) && $form->validate()) { $duplicateUser = $rows->one('users', ['username'=>$form->values['username'] ]); if ($duplicateUser) { $form->error('username', 'Uživatel tohoto jména již v systému je.'); } $memberId = null; if ($form->values['card_id']) { $card = $rows->one('cards', ['id'=>$form->values['card_id'], 'is_active'=>1]); $memberId = $card['member_id']; } if ($form->isValid) { $rows->insert('users', [ 'username' => $form->values['username'], 'name' => $form->values['name'], 'password' => password_hash($form->values['password'], PASSWORD_DEFAULT), 'member_id'=> $memberId ]); flash('Uživatel přidán.', 'success'); return redirect('/obsluha/'); } } return render('form', ['form'=>$form, 'title'=>'Přidat obsluhu']); }); route('', '/obsluha/upravit/{id}/', function ($req, $params){ if (!user()) return redirect('/login/'); $user = user(); if (!$user['is_superuser']) { flash('Obsluhu může upravovat jen admin.', 'warning'); return redirect('/'); } $id = $params['id']; /** @var Psr\Http\Message\ServerRequestInterface $req */ /** @var severak\database\rows $rows */ $rows = di('rows'); $form = new form(['method'=>'post']); $form->field('username', ['label'=>'Uživatelské jméno']); $form->field('password', ['type'=>'password', 'label'=>'Heslo']); $form->field('password_again', ['type'=>'password', 'label'=>'Heslo znovu']); $form->field('name', ['required'=>true, 'type'=>'text', 'label'=>'Jméno']); $form->field('card_id', ['type'=>'number', 'label'=>'Číslo členské karty', 'id'=>'qrcode']); $form->field('is_active', ['type'=>'checkbox', 'label'=>'Aktivní?']); $form->field('is_superuser', ['type'=>'checkbox', 'label'=>'Je admin?']); $form->field('note', ['type'=>'textarea', 'label'=>'Poznámka']); $form->field('_sbt', ['label'=>'Uložit', 'type'=>'submit']); $form->rule('password_again', function ($v, $o){ return $v==$o['password']; }, 'Hesla se neshodují!'); if ($req->getMethod()=='POST' && $form->fill($req->getParsedBody())) { $form->validate(); $duplicateUser = $rows->one('users', ['username'=>$form->values['username'] ]); if ($duplicateUser && $duplicateUser['id']!=$id) { $form->error('username', 'Uživatel tohoto jména již v systému je.'); } if ($form->values['password'] && $form->values['password']!=$form->values['password_again']) { $form->error('password', 'Hesla se musí shodovat!'); } if ($form->isValid) { $update = $form->values; // TODO tohle je prasárna unset($update['id'], $update['password'], $update['password_again'], $update['card_id'], $update['_sbt']); if ($form->values['password'] && $form->values['password']!=$form->values['password_again']) { $update['password'] = password_hash($form->values['password'], PASSWORD_DEFAULT); } if ($form->values['card_id']) { $card = $rows->one('cards', ['id'=>$form->values['card_id'], 'is_active'=>1]); $update['member_id'] = $card['member_id']; } $rows->update('users', $update, $id); flash('Uživatel upraven.', 'success'); return redirect('/obsluha/'); } } else { $editedUser = $rows->one('users', $id); unset($editedUser['password']); if ($editedUser['member_id']) { $card = $rows->one('cards', ['member_id'=>$editedUser['member_id'], 'is_active'=>1]); if ($card) { $editedUser['card_id'] = $card['id']; } } $form->fill($editedUser); } return render('form', ['form'=>$form, 'title'=>'Upravit obsluhu']); });