An easy point of sale system with automatic inventory tracking. https://netsyms.biz/apps/nickelbox/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

action.php 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. <?php
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /**
  6. * Make things happen when buttons are pressed and forms submitted.
  7. */
  8. require_once __DIR__ . "/required.php";
  9. require_once __DIR__ . "/lib/userinfo.php";
  10. if ($VARS['action'] !== "signout") {
  11. dieifnotloggedin();
  12. }
  13. /**
  14. * Redirects back to the page ID in $_POST/$_GET['source'] with the given message ID.
  15. * The message will be displayed by the app.
  16. * @param string $msg message ID (see lang/messages.php)
  17. * @param string $arg If set, replaces "{arg}" in the message string when displayed to the user.
  18. */
  19. function returnToSender($msg, $arg = "") {
  20. global $VARS;
  21. if ($arg == "") {
  22. header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=" . $msg);
  23. } else {
  24. header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=$msg&arg=$arg");
  25. }
  26. die();
  27. }
  28. switch ($VARS['action']) {
  29. case "finish_transaction":
  30. header("Content-Type: application/json");
  31. $error = null;
  32. $oktx = null;
  33. $database->action(function ($database) {
  34. global $VARS, $binstack, $error, $oktx;
  35. $items = $VARS['items'];
  36. $payments = $VARS['payments'];
  37. $customer = $VARS['customer'];
  38. $register = $VARS['register'];
  39. $discountpercent = $VARS['discountpercent'];
  40. $cashid = null;
  41. $editing = false;
  42. if (isset($VARS['txid']) && $database->has('transactions', ['txid' => $VARS['txid']])) {
  43. $editing = true;
  44. $txid = $VARS['txid'];
  45. $cashid = $database->get('transactions', 'cashid', ['txid' => $txid]);
  46. if (!$database->has('cash_drawer', ['AND' => ['cashid' => $cashid, 'close' => null]])) {
  47. $error = lang("cash already closed", false);
  48. return false;
  49. }
  50. // Nuke the payments to make room for their replacements
  51. // Delete payments
  52. $oldpayments = $database->select('payments', ['payid', 'amount', 'type', 'certid'], ['txid' => $txid]);
  53. foreach ($oldpayments as $p) {
  54. // Reset gift card balances
  55. if (!is_null($p['certid'])) {
  56. $database->update('certificates', ['amount[+]' => $p['amount']], ['certid' => $p['certid']]);
  57. }
  58. $database->delete('payments', ['payid' => $p['payid']]);
  59. }
  60. }
  61. if ($customer != "" && !$database->has('customers', ['customerid' => $customer])) {
  62. $error = lang("invalid customer", false);
  63. return false;
  64. }
  65. if ($register != "" && !$database->has('registers', ['registerid' => $register])) {
  66. $error = lang("invalid register", false);
  67. return false;
  68. }
  69. if ($register != "" && !$database->has('cash_drawer', ['AND' => ['registerid' => $register, 'close' => null]])) {
  70. $error = lang("cash not open", false);
  71. return false;
  72. }
  73. if ($register != "" && $editing === false) {
  74. $cashid = $database->get('cash_drawer', 'cashid', ['AND' => ['registerid' => $register, 'close' => null]]);
  75. }
  76. $totalcharge = 0.00;
  77. $totalpaid = 0.00;
  78. $change = 0.0;
  79. foreach ($items as $i) {
  80. $totalcharge += $i['each'] * $i['qty'];
  81. if (!$binstack->has('items', ['itemid' => $i['id']])) {
  82. $error = lang("invalid item", false);
  83. return false;
  84. }
  85. }
  86. foreach ($payments as $p) {
  87. if (!$database->has('payment_types', ['typename' => $p['type']])) {
  88. $error = lang("invalid payment type", false);
  89. return false;
  90. }
  91. $totalpaid += $p['amount'];
  92. if ($p['type'] == "giftcard") {
  93. if (!$database->has('certificates', ['AND' => ['amount[>=]' => $p['amount'], 'deleted[!]' => 1, 'certcode' => $p['code']]])) {
  94. $error = lang("invalid giftcard", false);
  95. return false;
  96. }
  97. }
  98. }
  99. if (is_numeric($discountpercent) && $discountpercent > 0 && $discountpercent < 100) {
  100. $discountpercent = $discountpercent * 1.0;
  101. $totalcharge *= 1.0 - ($discountpercent / 100.0);
  102. } else {
  103. $discountpercent = 0.0;
  104. }
  105. if ($totalcharge > $totalpaid) {
  106. $error = lang("insufficient payment", false);
  107. return false;
  108. }
  109. if ($editing === true) {
  110. $database->update('transactions', [
  111. 'txdate' => date('Y-m-d H:i:s'),
  112. 'customerid' => ($customer != "" ? $customer : null),
  113. 'type' => 1,
  114. 'cashier' => $_SESSION['uid'],
  115. 'cashid' => $cashid,
  116. 'discountpercent' => $discountpercent
  117. ], [
  118. 'txid' => $txid
  119. ]);
  120. } else {
  121. $database->insert('transactions', [
  122. 'txdate' => date('Y-m-d H:i:s'),
  123. 'customerid' => ($customer != "" ? $customer : null),
  124. 'type' => 1,
  125. 'cashier' => $_SESSION['uid'],
  126. 'cashid' => $cashid,
  127. 'discountpercent' => $discountpercent
  128. ]);
  129. $txid = $database->id();
  130. }
  131. $olditems = $database->select('lines', ['itemid (id)', 'qty', 'lineid'], ['txid' => $txid]);
  132. foreach ($items as $i) {
  133. $item = $binstack->get('items', ['name', 'qty'], ['itemid' => $i['id']]);
  134. $database->insert('lines', [
  135. 'txid' => $txid,
  136. 'amount' => $i['each'],
  137. 'name' => $item['name'],
  138. 'itemid' => $i['id'],
  139. 'qty' => $i['qty']
  140. ]);
  141. $binstack->update('items', [
  142. 'qty[-]' => $i['qty']
  143. ], [
  144. 'itemid' => $i['id']
  145. ]);
  146. }
  147. foreach ($payments as $p) {
  148. $certid = null;
  149. if ($p['type'] == "giftcard") {
  150. $certid = $database->get('certificates', 'certid', ['certcode' => $p['code']]);
  151. }
  152. $type = $database->get('payment_types', 'typeid', ['typename' => $p['type']]);
  153. $database->insert('payments', [
  154. 'amount' => $p['amount'],
  155. 'data' => '',
  156. 'type' => $type,
  157. 'txid' => $txid,
  158. 'certid' => $certid
  159. ]);
  160. }
  161. if ($totalcharge < $totalpaid) {
  162. $change = $totalpaid - $totalcharge;
  163. $database->insert('payments', [
  164. 'amount' => $change * -1.0,
  165. 'data' => '',
  166. 'type' => 1,
  167. 'txid' => $txid,
  168. 'certid' => null
  169. ]);
  170. }
  171. foreach ($olditems as $i) {
  172. $database->delete('lines', ['lineid' => $i['lineid']]);
  173. $binstack->update('items', [
  174. 'qty[+]' => $i['qty']
  175. ], [
  176. 'itemid' => $i['id']
  177. ]);
  178. }
  179. $oktx = $txid;
  180. return true;
  181. });
  182. if (!is_null($error)) {
  183. exit(json_encode(["status" => "ERROR", "message" => $error]));
  184. } else {
  185. exit(json_encode(["status" => "OK", "txid" => $oktx]));
  186. }
  187. break;
  188. case "finish_return":
  189. header("Content-Type: application/json");
  190. $error = null;
  191. $oktx = null;
  192. $database->action(function ($database) {
  193. global $VARS, $binstack, $error, $oktx;
  194. $items = $VARS['items'];
  195. $payments = $VARS['payments'];
  196. $customer = $VARS['customer'];
  197. $register = $VARS['register'];
  198. $cashid = null;
  199. if ($customer != "" && !$database->has('customers', ['customerid' => $customer])) {
  200. $error = lang("invalid customer", false);
  201. return false;
  202. }
  203. if ($register != "" && !$database->has('registers', ['registerid' => $register])) {
  204. $error = lang("invalid register", false);
  205. return false;
  206. }
  207. if ($register != "" && !$database->has('cash_drawer', ['AND' => ['registerid' => $register, 'close' => null]])) {
  208. $error = lang("cash not open", false);
  209. return false;
  210. }
  211. if ($register != "") {
  212. $cashid = $database->get('cash_drawer', 'cashid', ['AND' => ['registerid' => $register, 'close' => null]]);
  213. }
  214. $totaldue = 0.00;
  215. $totalrefund = 0.00;
  216. foreach ($items as $i) {
  217. $totaldue += $i['each'] * $i['qty'];
  218. if (!$binstack->has('items', ['itemid' => $i['id']])) {
  219. $error = lang("invalid item", false);
  220. return false;
  221. }
  222. }
  223. foreach ($payments as $p) {
  224. if (!$database->has('payment_types', ['typename' => $p['type']])) {
  225. $error = lang("invalid payment type", false);
  226. return false;
  227. }
  228. $totalrefund += $p['amount'];
  229. if ($p['type'] == "giftcard") {
  230. if (!$database->has('certificates', ['AND' => ['amount[>=]' => $p['amount'], 'deleted[!]' => 1, 'certcode' => $p['code']]])) {
  231. $error = lang("invalid giftcard", false);
  232. return false;
  233. }
  234. }
  235. }
  236. $database->insert('transactions', [
  237. 'txdate' => date('Y-m-d H:i:s'),
  238. 'customerid' => ($customer != "" ? $customer : null),
  239. 'type' => 2,
  240. 'cashier' => $_SESSION['uid'],
  241. 'cashid' => $cashid,
  242. 'discountpercent' => 0.0
  243. ]);
  244. $txid = $database->id();
  245. foreach ($items as $i) {
  246. $item = $binstack->get('items', ['name', 'qty'], ['itemid' => $i['id']]);
  247. $database->insert('lines', [
  248. 'txid' => $txid,
  249. 'amount' => $i['each'],
  250. 'name' => $item['name'],
  251. 'itemid' => $i['id'],
  252. 'qty' => $i['qty'] * -1.0
  253. ]);
  254. }
  255. foreach ($payments as $p) {
  256. $certid = null;
  257. if ($p['type'] == "giftcard") {
  258. $certid = $database->get('certificates', 'certid', ['certcode' => $p['code']]);
  259. $database->update('certificates', ['amount[+]' => $p['amount']], ['certid' => $certid]);
  260. }
  261. $type = $database->get('payment_types', 'typeid', ['typename' => $p['type']]);
  262. $database->insert('payments', [
  263. 'amount' => $p['amount'] * -1.0,
  264. 'data' => '',
  265. 'type' => $type,
  266. 'txid' => $txid,
  267. 'certid' => $certid
  268. ]);
  269. }
  270. $oktx = $txid;
  271. return true;
  272. });
  273. if (!is_null($error)) {
  274. exit(json_encode(["status" => "ERROR", "message" => $error]));
  275. } else {
  276. exit(json_encode(["status" => "OK", "txid" => $oktx]));
  277. }
  278. break;
  279. case "getreceipt":
  280. require_once __DIR__ . "/lib/generatereceipt.php";
  281. $format = "html";
  282. $width = 64;
  283. if (isset($VARS['width']) && preg_match("/[0-9]+/", $VARS['width']) && (int) $VARS['width'] > 0) {
  284. $width = (int) $VARS['width'];
  285. }
  286. if (isset($VARS['format'])) {
  287. $format = $VARS['format'];
  288. }
  289. if (!$database->has('transactions', ['txid' => $VARS['txid']])) {
  290. header("Content-Type: application/json");
  291. exit(json_encode(["status" => "ERROR", "txid" => null]));
  292. }
  293. $receipt = GenerateReceipt::getReceipt(GenerateReceipt::RECEIPT_TYPE_TRANSACTION, $VARS['txid']);
  294. exit(GenerateReceipt::outputReceipt($receipt, $format, $width, "Tx. #" . $VARS['txid']));
  295. break;
  296. case "transactionsearch":
  297. header("Content-Type: application/json");
  298. if (!is_empty($VARS['q'])) {
  299. $where["AND"]["OR"] = [
  300. "txid" => $VARS['q'],
  301. "name[~]" => $VARS['q'],
  302. "email[~]" => $VARS['q'],
  303. "phone[~]" => $VARS['q']
  304. ];
  305. } else {
  306. exit(json_encode(["status" => "ERROR", "transactions" => false]));
  307. }
  308. $where["LIMIT"] = 50;
  309. $transactions = $database->select('transactions', [
  310. '[>]customers' => 'customerid',
  311. '[>]cash_drawer' => 'cashid',
  312. '[>]registers' => ['cash_drawer.registerid' => 'registerid'],
  313. ], [
  314. 'txid',
  315. 'txdate',
  316. 'type',
  317. 'cashier (cashierid)',
  318. 'transactions.cashid',
  319. 'cash_drawer.registerid',
  320. 'registers.registername',
  321. 'cash_drawer.open',
  322. 'cash_drawer.close',
  323. 'customerid',
  324. 'customer' => [
  325. 'name',
  326. 'email',
  327. 'phone',
  328. 'address'
  329. ]], $where);
  330. for ($i = 0; $i < count($transactions); $i++) {
  331. if (is_null($transactions[$i]['close']) && !is_null($transactions[$i]['open'])) {
  332. $transactions[$i]['editable'] = true;
  333. } else {
  334. $transactions[$i]['editable'] = false;
  335. }
  336. if (!is_null($transactions[$i]['cashierid'])) {
  337. $cashier = getUserByID($transactions[$i]['cashierid']);
  338. $transactions[$i]['cashier'] = [
  339. "name" => $cashier['name'],
  340. "username" => $cashier['username']
  341. ];
  342. }
  343. }
  344. $transactions = (count($transactions) > 0 ? $transactions : false);
  345. exit(json_encode(["status" => "OK", "transactions" => $transactions]));
  346. case "itemsearch":
  347. header("Content-Type: application/json");
  348. if (!is_empty($VARS['q'])) {
  349. $where["AND"]["OR"] = [
  350. "name[~]" => $VARS['q'],
  351. "code1[~]" => $VARS['q'],
  352. "code2[~]" => $VARS['q']
  353. ];
  354. } else {
  355. exit(json_encode(["status" => "ERROR", "items" => false]));
  356. }
  357. $items = $binstack->select('items', [
  358. 'itemid (id)',
  359. 'name',
  360. 'code1',
  361. 'code2',
  362. 'cost',
  363. 'price'
  364. ], $where);
  365. if (!empty($VARS['customer']) && $database->has('customers', ['customerid' => $VARS['customer']])) {
  366. for ($n = 0; $n < count($items); $n++) {
  367. $i = $items[$n];
  368. if ($database->has('customer_pricing', ['AND' => ['itemid' => $i['id'], 'customerid' => $VARS['customer']]])) {
  369. $items[$n]['price'] = $database->get('customer_pricing', 'price', ['AND' => ['itemid' => $i['id'], 'customerid' => $VARS['customer']]]);
  370. }
  371. }
  372. }
  373. $items = (count($items) > 0 ? $items : false);
  374. exit(json_encode(["status" => "OK", "items" => $items]));
  375. case "getgriditems":
  376. header("Content-Type: application/json");
  377. $items = $binstack->select('items', [
  378. 'itemid (id)', 'name', 'price', 'code1', 'code2'
  379. ], [
  380. 'AND' => ['price[!]' => null, 'price[!]' => 0]
  381. ]);
  382. if (!empty($VARS['customer']) && $database->has('customers', ['customerid' => $VARS['customer']])) {
  383. for ($n = 0; $n < count($items); $n++) {
  384. $i = $items[$n];
  385. if ($database->has('customer_pricing', ['AND' => ['itemid' => $i['id'], 'customerid' => $VARS['customer']]])) {
  386. $items[$n]['price'] = $database->get('customer_pricing', 'price', ['AND' => ['itemid' => $i['id'], 'customerid' => $VARS['customer']]]);
  387. }
  388. }
  389. }
  390. for ($n = 0; $n < count($items); $n++) {
  391. if ($items[$n]['code1'] != "") {
  392. $items[$n]['code'] = $items[$n]["code1"];
  393. } else if ($items[$n]['code1'] == "" && $items[$n]['code1'] != "") {
  394. $items[$n]['code'] = $items[$n]["code2"];
  395. } else if (code == "") {
  396. $items[$n]['code'] = "---";
  397. }
  398. }
  399. $items = (count($items) > 0 ? $items : false);
  400. exit(json_encode(["status" => "OK", "items" => $items]));
  401. case "customersearch":
  402. header("Content-Type: application/json");
  403. if (!is_empty($VARS['q'])) {
  404. $where["AND"]["OR"] = [
  405. "customerid" => $VARS['q'],
  406. "name[~]" => $VARS['q'],
  407. "email[~]" => $VARS['q'],
  408. "phone[~]" => $VARS['q']
  409. ];
  410. } else {
  411. exit(json_encode(["status" => "ERROR", "customers" => false]));
  412. }
  413. $where["LIMIT"] = 10;
  414. $customers = $database->select('customers', [
  415. 'customerid (id)',
  416. 'name',
  417. 'email',
  418. 'phone',
  419. 'address',
  420. 'notes'
  421. ], $where);
  422. $customers = (count($customers) > 0 ? $customers : false);
  423. exit(json_encode(["status" => "OK", "customers" => $customers]));
  424. case "giftcard_lookup":
  425. header("Content-Type: application/json");
  426. $code = $VARS['code'];
  427. if (empty($code)) {
  428. exit(json_encode(["status" => "ERROR", "cards" => []]));
  429. }
  430. $cards = $database->select('certificates', ['certid (id)', 'certcode (code)', 'amount (balance)', 'start_amount (amount)'], ['certcode' => $code]);
  431. exit(json_encode(["status" => "OK", "cards" => $cards]));
  432. break;
  433. case "editcustomer":
  434. $insert = true;
  435. if (is_empty($VARS['id'])) {
  436. $insert = true;
  437. } else {
  438. if ($database->has('customers', ['customerid' => $VARS['id']])) {
  439. $insert = false;
  440. } else {
  441. returnToSender("invalid_customerid");
  442. }
  443. }
  444. if (is_empty($VARS['name'])) {
  445. returnToSender('invalid_parameters');
  446. }
  447. $data = [
  448. 'name' => $VARS['name'],
  449. 'email' => $VARS['email'],
  450. 'phone' => $VARS['phone'],
  451. 'address' => $VARS['address'],
  452. 'notes' => $VARS['notes']
  453. ];
  454. $customerid = null;
  455. if ($insert) {
  456. $database->insert('customers', $data);
  457. $customerid = $database->id();
  458. } else {
  459. $database->update('customers', $data, ['customerid' => $VARS['id']]);
  460. $customerid = $VARS['id'];
  461. }
  462. if (!is_null($customerid)) {
  463. $custprices = $VARS['pricing'];
  464. $newcustprices = [];
  465. $oldcustprices = $database->select('customer_pricing', ['itemid (item)', 'price'], ['customerid' => $customerid]);
  466. foreach ($custprices as $cp) {
  467. if (!$binstack->has('items', ['itemid' => $cp['item']])) {
  468. continue;
  469. }
  470. if (!is_numeric($cp['price'])) {
  471. continue;
  472. }
  473. $newcustprices[] = $cp;
  474. $oldcustprices = array_filter($oldcustprices, function ($var) {
  475. if ($cp['item'] == $var['item']) {
  476. return false;
  477. }
  478. return true;
  479. });
  480. }
  481. foreach ($oldcustprices as $cp) {
  482. $database->delete('customer_pricing', ['AND' => ['itemid' => $cp['item'], 'customerid' => $customerid]]);
  483. }
  484. foreach ($newcustprices as $cp) {
  485. if ($database->has('customer_pricing', ['AND' => ['itemid' => $cp['item'], 'customerid' => $customerid]])) {
  486. $database->update('customer_pricing', ['price' => $cp['price']], ['AND' => ['itemid' => $cp['item'], 'customerid' => $customerid]]);
  487. } else {
  488. $database->insert('customer_pricing', ['price' => $cp['price'], 'itemid' => $cp['item'], 'customerid' => $customerid]);
  489. }
  490. }
  491. }
  492. returnToSender("customer_saved");
  493. case "set_register":
  494. $regid = $VARS['register'];
  495. if (!$database->has('registers', ['registerid' => $regid])) {
  496. returnToSender("invalid_parameters");
  497. }
  498. if (!$database->has('cash_drawer', ['AND' => ['registerid' => $regid, 'close' => null]])) {
  499. returnToSender("cash_not_open");
  500. }
  501. $cashid = $database->get('cash_drawer', 'cashid', ['AND' => ['registerid' => $regid, 'close' => null]]);
  502. $_SESSION['register'] = (int) $regid;
  503. returnToSender("register_set");
  504. break;
  505. case "opencash":
  506. $regid = $VARS['register'];
  507. $start = $VARS['startamount'];
  508. if (!$database->has('registers', ['registerid' => $regid])) {
  509. returnToSender("invalid_parameters");
  510. }
  511. if ($database->has('cash_drawer', ['AND' => ['registerid' => $regid, 'close' => null]])) {
  512. returnToSender("cash_already_open");
  513. }
  514. if (!is_numeric($start) || (float) $start < 0) {
  515. $start = 0.0;
  516. }
  517. $database->insert('cash_drawer', [
  518. 'registerid' => $regid,
  519. 'open' => date('Y-m-d H:i:s'),
  520. 'close' => null,
  521. 'start_amount' => $start,
  522. 'end_amount' => null
  523. ]);
  524. returnToSender("cash_opened");
  525. break;
  526. case "closecash":
  527. $regid = $VARS['register'];
  528. if (!$database->has('registers', ['registerid' => $regid])) {
  529. returnToSender("invalid_parameters");
  530. }
  531. if (!$database->has('cash_drawer', ['AND' => ['registerid' => $regid, 'close' => null]])) {
  532. returnToSender("cash_not_open");
  533. }
  534. $cash = $database->get('cash_drawer', ['cashid', 'start_amount'], ['AND' => ['registerid' => $regid, 'close' => null]]);
  535. $balance = (float) $cash['start_amount'];
  536. $rows = $database->select("payments", [
  537. "[>]transactions" => ['txid' => 'txid']
  538. ], 'amount', [
  539. 'AND' => [
  540. 'transactions.cashid' => $cash['cashid'],
  541. 'payments.type' => 1
  542. ]
  543. ]);
  544. foreach ($rows as $row) {
  545. $balance += $row;
  546. }
  547. $database->update('cash_drawer', [
  548. 'close' => date('Y-m-d H:i:s'),
  549. 'end_amount' => $balance
  550. ], [
  551. 'cashid' => $cash['cashid']
  552. ]);
  553. returnToSender("cash_closed");
  554. break;
  555. case "editregister":
  556. $insert = true;
  557. if (empty($VARS['id'])) {
  558. $insert = true;
  559. } else {
  560. if ($database->has('registers', ['registerid' => $VARS['id']])) {
  561. $insert = false;
  562. } else {
  563. returnToSender("invalid_parameters");
  564. }
  565. }
  566. if (is_empty($VARS['name'])) {
  567. returnToSender('invalid_parameters');
  568. }
  569. if ($database->has('registers', ['AND' => ['registerid[!]' => $VARS['id'], 'registername' => $VARS['name']]])) {
  570. returnToSender("register_name_taken");
  571. }
  572. $data = [
  573. 'registername' => $VARS['name']
  574. ];
  575. if ($insert) {
  576. $database->insert('registers', $data);
  577. } else {
  578. $database->update('registers', $data, ['registerid' => $VARS['id']]);
  579. }
  580. returnToSender("register_saved");
  581. case "xreport":
  582. require_once __DIR__ . "/lib/generatereceipt.php";
  583. $format = "html";
  584. $width = 64;
  585. if (isset($VARS['width']) && preg_match("/[0-9]+/", $VARS['width']) && (int) $VARS['width'] > 0) {
  586. $width = (int) $VARS['width'];
  587. }
  588. if (isset($VARS['format'])) {
  589. $format = $VARS['format'];
  590. }
  591. if (!$database->has('cash_drawer', ['AND' => ['registerid' => $VARS['register'], 'open[!]' => null, 'close' => null]])) {
  592. header("Content-Type: application/json");
  593. exit(json_encode(["status" => "ERROR"]));
  594. }
  595. $receipt = GenerateReceipt::getReceipt(GenerateReceipt::RECEIPT_TYPE_X, $VARS['register']);
  596. exit(GenerateReceipt::outputReceipt($receipt, $format, $width, "X Report"));
  597. break;
  598. case "zreport":
  599. require_once __DIR__ . "/lib/generatereceipt.php";
  600. $format = "html";
  601. $width = 64;
  602. if (isset($VARS['width']) && preg_match("/[0-9]+/", $VARS['width']) && (int) $VARS['width'] > 0) {
  603. $width = (int) $VARS['width'];
  604. }
  605. if (isset($VARS['format'])) {
  606. $format = $VARS['format'];
  607. }
  608. if (!$database->has('cash_drawer', ['AND' => ['open[!]' => null, 'close[!]' => null, 'cashid' => $VARS['cash']]])) {
  609. header("Content-Type: application/json");
  610. exit(json_encode(["status" => "ERROR"]));
  611. }
  612. $receipt = GenerateReceipt::getReceipt(GenerateReceipt::RECEIPT_TYPE_Z, $VARS['cash']);
  613. exit(GenerateReceipt::outputReceipt($receipt, $format, $width, "Z Report"));
  614. break;
  615. case "session_keepalive":
  616. header("Content-Type: application/json");
  617. exit(json_encode(["status" => "OK"]));
  618. case "signout":
  619. session_destroy();
  620. header('Location: index.php');
  621. die("Logged out.");
  622. }