diff --git a/action.php b/action.php index 6f589ef..4ef89d1 100644 --- a/action.php +++ b/action.php @@ -200,6 +200,107 @@ switch ($VARS['action']) { return true; }); + if (!is_null($error)) { + exit(json_encode(["status" => "ERROR", "message" => $error])); + } else { + exit(json_encode(["status" => "OK", "txid" => $oktx])); + } + break; + case "finish_return": + header("Content-Type: application/json"); + $error = null; + $oktx = null; + $database->action(function ($database) { + global $VARS, $binstack, $error, $oktx; + + $items = $VARS['items']; + $payments = $VARS['payments']; + $customer = $VARS['customer']; + $register = $VARS['register']; + $cashid = null; + + if ($customer != "" && !$database->has('customers', ['customerid' => $customer])) { + $error = lang("invalid customer", false); + return false; + } + if ($register != "" && !$database->has('registers', ['registerid' => $register])) { + $error = lang("invalid register", false); + return false; + } + if ($register != "" && !$database->has('cash_drawer', ['AND' => ['registerid' => $register, 'close' => null]])) { + $error = lang("cash not open", false); + return false; + } + + if ($register != "") { + $cashid = $database->get('cash_drawer', 'cashid', ['AND' => ['registerid' => $register, 'close' => null]]); + } + + $totaldue = 0.00; + $totalrefund = 0.00; + foreach ($items as $i) { + $totaldue += $i['each'] * $i['qty']; + if (!$binstack->has('items', ['itemid' => $i['id']])) { + $error = lang("invalid item", false); + return false; + } + } + foreach ($payments as $p) { + if (!$database->has('payment_types', ['typename' => $p['type']])) { + $error = lang("invalid payment type", false); + return false; + } + $totalrefund += $p['amount']; + if ($p['type'] == "giftcard") { + if (!$database->has('certificates', ['AND' => ['amount[>=]' => $p['amount'], 'deleted[!]' => 1, 'certcode' => $p['code']]])) { + $error = lang("invalid giftcard", false); + return false; + } + } + } + + $database->insert('transactions', [ + 'txdate' => date('Y-m-d H:i:s'), + 'customerid' => ($customer != "" ? $customer : null), + 'type' => 2, + 'cashier' => $_SESSION['uid'], + 'cashid' => $cashid, + 'discountpercent' => 0.0 + ]); + $txid = $database->id(); + + foreach ($items as $i) { + $item = $binstack->get('items', ['name', 'qty'], ['itemid' => $i['id']]); + + $database->insert('lines', [ + 'txid' => $txid, + 'amount' => $i['each'], + 'name' => $item['name'], + 'itemid' => $i['id'], + 'qty' => $i['qty'] * -1.0 + ]); + } + + foreach ($payments as $p) { + $certid = null; + if ($p['type'] == "giftcard") { + $certid = $database->get('certificates', 'certid', ['certcode' => $p['code']]); + $database->update('certificates', ['amount[+]' => $p['amount']], ['certid' => $certid]); + } + $type = $database->get('payment_types', 'typeid', ['typename' => $p['type']]); + $database->insert('payments', [ + 'amount' => $p['amount'] * -1.0, + 'data' => '', + 'type' => $type, + 'txid' => $txid, + 'certid' => $certid + ]); + } + + $oktx = $txid; + return true; + }); + if (!is_null($error)) { exit(json_encode(["status" => "ERROR", "message" => $error])); } else { diff --git a/lang/en_us.php b/lang/en_us.php index 1dd1ebe..274ad8a 100644 --- a/lang/en_us.php +++ b/lang/en_us.php @@ -121,4 +121,8 @@ define("STRINGS", [ "cash already closed" => "Cash already closed, cannot edit this transaction. Process a return instead.", "update" => "Update", "transaction search" => "Search transactions (by Tx ID or customer)", + "return" => "Return", + "enter refund" => "Enter Refund", + "refund" => "Refund", + "cannot edit return transaction" => "Cannot edit a return transaction." ]); diff --git a/lang/messages.php b/lang/messages.php index a378b6e..7336b33 100644 --- a/lang/messages.php +++ b/lang/messages.php @@ -48,5 +48,9 @@ define("MESSAGES", [ "register_name_taken" => [ "string" => "register name taken", "type" => "danger" - ] + ], + "return_transaction_no_edit" => [ + "string" => "cannot edit return transaction", + "type" => "danger" + ], ]); diff --git a/lib/generatereceipt.php b/lib/generatereceipt.php index 4ffbcfd..e68c26a 100644 --- a/lib/generatereceipt.php +++ b/lib/generatereceipt.php @@ -14,7 +14,7 @@ class GenerateReceipt { const RECEIPT_TYPE_X = 2; const RECEIPT_TYPE_Z = 3; - static function transactionReceipt($transaction) { + private static function saleReceipt($transaction) { global $database; $receipt = new Receipt(); $tx = $database->get('transactions', ['txid', 'txdate', 'customerid', 'type', 'cashier', 'discountpercent'], ['txid' => $transaction]); @@ -90,6 +90,82 @@ class GenerateReceipt { return $receipt; } + private static function returnReceipt($transaction) { + global $database; + $receipt = new Receipt(); + $tx = $database->get('transactions', ['txid', 'txdate', 'customerid', 'type', 'cashier', 'discountpercent'], ['txid' => $transaction]); + // Info + $txid = $tx['txid']; + $datetime = date(DATETIME_FORMAT, strtotime($tx['txdate'])); + $type = $tx['type']; + $cashier = getUserByID($tx['cashier'])['name']; + $customerid = $tx['customerid']; + + // Items + $itemlines = []; + $items = $database->select('lines', ['amount', 'name', 'itemid', 'qty'], ['txid' => $txid]); + $subtotal = 0.0; + $paid = 0.0; + foreach ($items as $i) { + $itemlines[] = new ReceiptLine( + $i['name'], (float) $i['qty'] . '@' . number_format($i['amount'], 2), '$' . number_format($i['qty'] * $i['amount'] * 1.0, 2) + ); + $subtotal += $i['qty'] * $i['amount'] * 1.0; + } + + // Payments + $total = $subtotal * (1.0 - ((float) $tx['discountpercent'] / 100)); + $paymentlines = []; + $payments = $database->select('payments', [ + '[>]payment_types' => ['type' => 'typeid'] + ], [ + 'amount', 'type', 'typename', 'text' + ], [ + 'txid' => $txid + ]); + foreach ($payments as $p) { + $paymentlines[] = new ReceiptLine(lang($p['text'], false), "", '$' . number_format($p['amount'] * -1.0, 2)); + $paid += $p['amount'] * 1.0; + } + + // Totals + $subtotalline = new ReceiptLine("Subtotal:", "", '$' . number_format($subtotal, 2)); + $paidline = new ReceiptLine("Refund:", "", '$' . number_format($paid * -1.0, 2), ReceiptLine::LINEFORMAT_BOLD); + $totalline = new ReceiptLine("Total:", "", '$' . number_format($subtotal, 2), ReceiptLine::LINEFORMAT_BOLD); + + $receipt->appendLine(new ReceiptLine("Date: $datetime")); + $receipt->appendLine(new ReceiptLine("Tx. ID: $txid")); + $receipt->appendLine(new ReceiptLine("Cashier: $cashier")); + if (!is_null($customerid) && !empty($customerid)) { + $customer = $database->get('customers', 'name', ['customerid' => $customerid]); + $receipt->appendLine(new ReceiptLine("Customer: $customer")); + } + $receipt->appendBreak(); + $receipt->appendLines($itemlines); + $receipt->appendBreak(); + $receipt->appendLine($subtotalline); + $receipt->appendLine($totalline); + $receipt->appendBreak(); + $receipt->appendLines($paymentlines); + $receipt->appendBreak(); + $receipt->appendLine($paidline); + + return $receipt; + } + + static function transactionReceipt($transaction) { + global $database; + $txtype = $database->get('transactions', 'type', ['txid' => $transaction]); + switch ($txtype) { + case 1: + return GenerateReceipt::saleReceipt($transaction); + case 2: + return GenerateReceipt::returnReceipt($transaction); + default: + return new Receipt(); + } + } + static function xReceipt($registerid) { global $database; $receipt = new Receipt(); diff --git a/pages/pos.php b/pages/pos.php index ddc2ace..1133329 100644 --- a/pages/pos.php +++ b/pages/pos.php @@ -22,12 +22,22 @@ if (isset($_GET['switch']) || !isset($_SESSION['register']) || !$registeropen) { $items = []; $payments = []; $editing = false; + $returning = false; if (isset($VARS['txid']) && $database->has('transactions', ['txid' => $VARS['txid']])) { - $editing = true; - $items = $database->select('lines', ['lineid', 'amount', 'name', 'itemid', 'qty'], ['txid' => $VARS['txid']]); - $payments = $database->select('payments', ['[>]certificates' => 'certid', '[>]payment_types' => ['type' => 'typeid']], ['payments.amount', 'typename', 'icon', 'text', 'certcode'], ['txid' => $VARS['txid']]); - $tx = $database->get('transactions', ['[>]customers' => 'customerid'], ['txid', 'discountpercent', 'transactions.customerid', 'customers.name (customername)'], ['txid' => $VARS['txid']]); - echo ""; + $tx = $database->get('transactions', ['[>]customers' => 'customerid'], ['txid', 'discountpercent', 'transactions.customerid', 'customers.name (customername)', 'cashid', 'type'], ['txid' => $VARS['txid']]); + if ($tx['type'] != 1) { + header('Location: app.php?page=pos&msg=return_transaction_no_edit'); + die(); + } + $items = $database->select('lines', ['lineid', 'amount', 'name', 'itemid', 'qty'], ['txid' => $tx['txid']]); + if ($database->has('cash_drawer', ['AND' => ['cashid' => $tx['cashid'], 'open[!]' => null, 'close' => null]])) { + $editing = true; + $payments = $database->select('payments', ['[>]certificates' => 'certid', '[>]payment_types' => ['type' => 'typeid']], ['payments.amount', 'typename', 'icon', 'text', 'certcode'], ['txid' => $tx['txid']]); + echo ""; + } else { + $returning = true; + echo ""; + } } ?>