diff --git a/action.php b/action.php
index 131202e..b5fcae0 100644
--- a/action.php
+++ b/action.php
@@ -144,41 +144,55 @@ switch ($VARS['action']) {
break;
case "getreceipt":
- header("Content-Type: text/html");
+ require_once __DIR__ . "/lib/receipts.php";
+ $format = "html";
+ $width = 64;
+ if (isset($VARS['width']) && preg_match("/[0-9]+/", $VARS['width']) && (int) $VARS['width'] > 0) {
+ $width = (int) $VARS['width'];
+ }
+ if (isset($VARS['format'])) {
+ switch ($VARS['format']) {
+ case "text":
+ $format = "text";
+ header("Content-Type: text/plain");
+ break;
+ case "json":
+ $format = "json";
+ header("Content-Type: application/json");
+ break;
+ default:
+ $format = "html";
+ header("Content-Type: text/html");
+ }
+ }
if (!$database->has('transactions', ['txid' => $VARS['txid']])) {
+ header("Content-Type: application/json");
exit(json_encode(["status" => "ERROR", "txid" => null]));
}
-
+ $receipt = new Receipt();
$tx = $database->get('transactions', ['txid', 'txdate', 'customerid', 'type', 'cashier', 'discountpercent'], ['txid' => $VARS['txid']]);
-
+ // Info
$txid = $tx['txid'];
$datetime = date(DATETIME_FORMAT, strtotime($tx['txdate']));
$type = $tx['type'];
$cashier = getUserByID($tx['cashier'])['name'];
$customerid = $tx['customerid'];
- $customerline = "";
- if (!is_null($customerid) && !empty($customerid)) {
- $customerline = "
Customer: " . $database->get('customers', 'name', ['customerid' => $customerid]);
- }
- $itemhtml = "";
+ // Items
+ $itemlines = [];
$items = $database->select('lines', ['amount', 'name', 'itemid', 'qty'], ['txid' => $txid]);
$subtotal = 0.0;
$paid = 0.0;
foreach ($items as $i) {
- $itemhtml .= "\n";
- $itemhtml .= '
';
- $itemhtml .= '
' . $i['name'] . '
';
- $itemhtml .= '
$' . number_format($i['amount'], 2) . '
';
- $itemhtml .= '
x' . (float) $i['qty'] . '
';
- $itemhtml .= '
$' . number_format($i['qty'] * $i['amount'] * 1.0, 2) . '
';
- $itemhtml .= '
';
+ $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));
-
- $paymenthtml = "";
+ $paymentlines = [];
$payments = $database->select('payments', [
'[>]payment_types' => ['type' => 'typeid']
], [
@@ -190,63 +204,54 @@ switch ($VARS['action']) {
if ($p['amount'] < 0) {
continue;
}
- $paymenthtml .= "\n";
- $paymenthtml .= '';
- $paymenthtml .= '
' . lang($p['text'], false) . '
';
- $paymenthtml .= '
$' . number_format($p['amount'] * 1.0, 2) . '
';
- $paymenthtml .= '
';
+ $paymentlines[] = new ReceiptLine(lang($p['text'], false), "", '$' . number_format($p['amount'] * 1.0, 2));
$paid += $p['amount'] * 1.0;
}
-
$change = $paid - $total;
if ($change <= 0) {
$change = 0.0;
}
- $subtotalstr = number_format($subtotal, 2);
- $paidstr = number_format($paid, 2);
- $changestr = number_format($change, 2);
- $totalstr = $subtotalstr;
- $discountstr = "";
- if ($tx['discountpercent'] > 0) {
- $discountstr = 'Discount: ' . (float) $tx['discountpercent'] . '% off
';
- $totalstr = number_format($total, 2);
- }
+ // Totals
+ $subtotalline = new ReceiptLine("Subtotal:", "", '$' . number_format($subtotal, 2));
+ $paidline = new ReceiptLine("Paid:", "", '$' . number_format($paid, 2), ReceiptLine::LINEFORMAT_BOLD);
+ $changeline = new ReceiptLine("Change:", "", '$' . number_format($change, 2), ReceiptLine::LINEFORMAT_BOLD);
+ $totalline = new ReceiptLine("Total:", "", '$' . number_format($subtotal, 2), ReceiptLine::LINEFORMAT_BOLD);
- $html = <<
-
-
-Tx #$txid
-
-
-Date: $datetime
-Tx. ID: $txid
-Cashier: $cashier
-$customerline
-
-
-$itemhtml
-
-
-Subtotal: $$subtotalstr
-$discountstr
-Total: $$totalstr
-
-
-$paymenthtml
-
-
-Paid: $$paidstr
-Change: $$changestr
-END;
- exit($html);
+ $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);
+ if ($tx['discountpercent'] > 0) {
+ $receipt->appendLine(new ReceiptLine("Discount:", "", (float) $tx['discountpercent'] . '% off'));
+ $totalline = new ReceiptLine("Total:", "", '$' . number_format($total, 2), ReceiptLine::LINEFORMAT_BOLD);
+ }
+ $receipt->appendLine($totalline);
+ $receipt->appendBreak();
+ $receipt->appendLines($paymentlines);
+ $receipt->appendBreak();
+ $receipt->appendLine($paidline);
+ $receipt->appendLine($changeline);
+
+ $output = "";
+ switch ($format) {
+ case "text":
+ $output = $receipt->getPlainText($width);
+ break;
+ case "json":
+ $output = $receipt->getJson($width);
+ break;
+ default:
+ $output = $receipt->getHtml("Tx. #$txid");
+ }
+ exit($output);
break;
case "itemsearch":
header("Content-Type: application/json");
diff --git a/lib/receipts.php b/lib/receipts.php
new file mode 100644
index 0000000..1374054
--- /dev/null
+++ b/lib/receipts.php
@@ -0,0 +1,240 @@
+left = $l;
+ $this->middle = $m;
+ $this->right = $r;
+ $this->format = $f;
+ }
+
+ function getLeft() {
+ return $this->left;
+ }
+
+ function getMiddle() {
+ return $this->middle;
+ }
+
+ function getRight() {
+ return $this->right;
+ }
+
+ function hasFormat($format) {
+ return ($this->format & $format);
+ }
+
+ function getHtml() {
+ if ($this->hasFormat($this::LINEFORMAT_HR)) {
+ return "
";
+ }
+ $html = "";
+ if (!empty($this->left)) {
+ $html .= '' . htmlspecialchars($this->left) . ' ';
+ }
+ if (!empty($this->middle)) {
+ $html .= '' . htmlspecialchars($this->middle) . ' ';
+ }
+ if (!empty($this->right)) {
+ $html .= '' . htmlspecialchars($this->right) . '';
+ }
+ $classes = ["flex"];
+ if ($this->hasFormat($this::LINEFORMAT_BOLD)) {
+ $classes[] = "bold";
+ }
+ if ($this->hasFormat($this::LINEFORMAT_CENTER)) {
+ $classes[] = "centered";
+ }
+ $classstr = implode(" ", $classes);
+ return "$html
";
+ }
+
+ function getPlainText($width) {
+ if ($this->hasFormat($this::LINEFORMAT_HR)) {
+ return str_repeat("-", $width);
+ }
+ $left = $this->left;
+ $middle = $this->middle;
+ $right = $this->right;
+ $leftln = strlen($left);
+ $middleln = strlen($middle);
+ $rightln = strlen($right);
+ if ($middleln > 0) {
+ $middleln++;
+ $middle = " " . $middle;
+ }
+ if ($rightln > 0) {
+ $rightln++;
+ $right = " " . $right;
+ }
+ $strln = $leftln + $middleln + $rightln;
+ if ($strln < $width) {
+ if ($this->hasFormat($this::LINEFORMAT_CENTER)) {
+ return str_pad($left . $middle . $right, $width, " ", STR_PAD_BOTH);
+ } else {
+ $middle = str_pad($middle, $width - $leftln - $rightln, " ", STR_PAD_BOTH);
+ }
+ } else if ($strln > $width) {
+ $loseln = $strln - $width;
+ $left = substr($this->left, 0, $leftln - $loseln);
+ }
+ return $left . $middle . $right;
+ }
+
+ function getArray($width = 64) {
+ $data = [
+ "left" => $this->left,
+ "middle" => $this->middle,
+ "right" => $this->right,
+ "text" => $this->getPlainText($width),
+ "format" => []
+ ];
+ if ($this->hasFormat($this::LINEFORMAT_PLAIN)) {
+ $data['format'][] = "plain";
+ }
+ if ($this->hasFormat($this::LINEFORMAT_BOLD)) {
+ $data['format'][] = "bold";
+ }
+ if ($this->hasFormat($this::LINEFORMAT_HR)) {
+ $data['format'][] = "hr";
+ }
+ if ($this->hasFormat($this::LINEFORMAT_CENTER)) {
+ $data['format'][] = "center";
+ }
+ return $data;
+ }
+
+}
+
+class Receipt {
+
+ private $lines = [];
+ private $header = [];
+ private $footer = [];
+
+ function __construct() {
+
+ }
+
+ function appendLine(ReceiptLine $line) {
+ $this->lines[] = $line;
+ }
+
+ function appendLines($lines) {
+ foreach ($lines as $l) {
+ $this->lines[] = $l;
+ }
+ }
+
+ function appendHeader(ReceiptLine $line) {
+ $this->header[] = $line;
+ }
+
+ function appendFooter(ReceiptLine $line) {
+ $this->footer[] = $line;
+ }
+
+ function appendBreak() {
+ $this->lines[] = new ReceiptLine("", "", "", ReceiptLine::LINEFORMAT_HR);
+ }
+
+ function getHtml($title = "") {
+ global $SECURE_NONCE;
+ $html = <<
+
+
+$title
+
+END;
+ if (count($this->header) > 0) {
+ foreach ($this->header as $line) {
+ $html .= $line->getHtml() . "\n";
+ }
+ $html .= (new ReceiptLine("", "", "", ReceiptLine::LINEFORMAT_HR))->getHtml();
+ }
+ foreach ($this->lines as $line) {
+ $html .= $line->getHtml() . "\n";
+ }
+ if (count($this->footer) > 0) {
+ $html .= (new ReceiptLine("", "", "", ReceiptLine::LINEFORMAT_HR))->getHtml();
+ foreach ($this->footer as $line) {
+ $html .= $line->getHtml() . "\n";
+ }
+ }
+ return $html;
+ }
+
+ function getPlainText($width) {
+ $lines = [];
+ if (count($this->header) > 0) {
+ foreach ($this->header as $line) {
+ $lines[] = $line->getPlainText($width);
+ }
+ $lines[] = (new ReceiptLine("", "", "", ReceiptLine::LINEFORMAT_HR))->getPlainText($width);
+ }
+ foreach ($this->lines as $line) {
+ $lines[] = $line->getPlainText($width);
+ }
+ if (count($this->footer) > 0) {
+ $lines[] = (new ReceiptLine("", "", "", ReceiptLine::LINEFORMAT_HR))->getPlainText($width);
+ foreach ($this->footer as $line) {
+ $lines[] = $line->getPlainText($width);
+ }
+ }
+ return implode("\n", $lines);
+ }
+
+ function getArray($width = 64) {
+ $header = [];
+ $lines = [];
+ $footer = [];
+ foreach ($this->header as $line) {
+ $header[] = $line->getArray($width);
+ }
+ foreach ($this->lines as $line) {
+ $lines[] = $line->getArray($width);
+ }
+ foreach ($this->footer as $line) {
+ $footer[] = $line->getArray($width);
+ }
+ return ["header" => $header, "lines" => $lines, "footer" => $footer];
+ }
+
+ function getJson($width = 64) {
+ return json_encode($this->getArray($width));
+ }
+
+}