public function parse($str) { $ret = $this->default_json(); if (CoreLocal::get('memberID') == '0') { $ret['output'] = DisplayLib::boxMsg(_("Apply member number first"), _('No member selected'), false, array_merge(array('Member Search [ID]' => 'parseWrapper(\'ID\');'), DisplayLib::standardClearButton())); return $ret; } if ($str == 'ACCESS') { if (CoreLocal::get('AccessQuickMenu') != '' && class_exists('QuickMenuLauncher')) { $qm = new QuickMenuLauncher(); return $qm->parse('QM' . CoreLocal::get('AccessQuickMenu')); } else { $str = 'ACCESS0'; } } if ($str !== 'ACCESS6' && CoreLocal::get('AccessSelection') === '') { CoreLocal::set('AccessSelection', $str); $ret['main_frame'] = MiscLib::baseURL() . 'gui-modules/adminlogin.php?class=AccessProgramParser'; return $ret; } else { CoreLocal::set('AccessSelection', ''); } $selection = substr($str, 6); TransRecord::addRecord(array('upc' => 'ACCESS', 'description' => 'ACCESS SIGNUP', 'quantity' => 1, 'ItemQtty' => 1, 'numflag' => $selection)); $ret['output'] = DisplayLib::lastpage(); $ret['receipt'] = 'accessSignupSlip'; return $ret; }
/** Check for errors @return True or an error message string */ public function errorCheck() { if ($this->amount > CoreLocal::get("amtdue") + 0.005 && CoreLocal::get("amtdue") >= 0) { return DisplayLib::xboxMsg(_("tender cannot exceed purchase amount"), DisplayLib::standardClearButton()); } return true; }
public function errorCheck() { if ($this->amount - CoreLocal::get('amtdue') > 0 && CoreLocal::get('amtdue') > 0) { return DisplayLib::boxMsg(_('max tender is ') . CoreLocal::get('amtdue'), _('no change allowed'), false, DisplayLib::standardClearButton()); } return true; }
/** Check for errors @return True or an error message string */ public function errorCheck() { if (MiscLib::truncate2(CoreLocal::get("amtdue")) < MiscLib::truncate2($this->amount)) { return DisplayLib::xboxMsg(_("tender cannot exceed purchase amount"), DisplayLib::standardClearButton()); } return true; }
function check($str) { $this->ret = $this->default_json(); if (substr($str, -2) == "DA") { $strl = substr($str, 0, strlen($str) - 2); if (substr($str, 0, 2) == "VD") { $this->ret = PrehLib::percentDiscount(0, $this->ret); } elseif (!is_numeric($strl)) { return false; } elseif (CoreLocal::get("tenderTotal") != 0) { $this->ret['output'] = DisplayLib::boxMsg(_("discount not applicable after tender"), '', false, DisplayLib::standardClearButton()); } elseif ($strl > 50) { $this->ret['output'] = DisplayLib::boxMsg(_("discount exceeds maximum"), '', false, DisplayLib::standardClearButton()); } elseif ($strl <= 0) { $this->ret['output'] = DisplayLib::boxMsg(_("discount must be greater than zero"), '', false, DisplayLib::standardClearButton()); } elseif ($strl <= 50 and $strl > 0) { $this->ret = PrehLib::percentDiscount($strl, $this->ret); $this->ret['redraw_footer'] = true; } else { return false; } return true; } return false; }
function parse($str) { $json = $this->default_json(); $arg = $this->left; CoreLocal::set("sc", 1); $staffID = substr($arg, 0, 4); $pQuery = "select staffID,chargecode,blueLine from chargecodeview where chargecode = '" . $arg . "'"; $pConn = Database::pDataConnect(); $result = $pConn->query($pQuery); $num_rows = $pConn->num_rows($result); $row = $pConn->fetch_array($result); if ($num_rows == 0) { $json['output'] = DisplayLib::xboxMsg(_("unable to authenticate staff ") . $staffID, DisplayLib::standardClearButton()); CoreLocal::set("isStaff", 0); // apbw 03/05/05 SCR return $json; } else { CoreLocal::set("isStaff", 1); // apbw 03/05/05 SCR CoreLocal::set("memMsg", $row["blueLine"]); $tQuery = "update localtemptrans set card_no = '" . $staffID . "', percentDiscount = 15"; $tConn = Database::tDataConnect(); $this->addscDiscount(); TransRecord::discountnotify(15); $tConn->query($tQuery); Database::getsubtotals(); $chk = self::ttl(); if ($chk !== True) { $json['main_frame'] = $chk; return $json; } CoreLocal::set("runningTotal", CoreLocal::get("amtdue")); return self::tender("MI", CoreLocal::get("runningTotal") * 100); } }
public function handle($upc, $json) { $my_url = MiscLib::base_url(); switch (ltrim($upc, '0')) { case '8006': if (CoreLocal::get("memberID") == 0) { $json['main_frame'] = $my_url . 'gui-modules/memlist.php'; } else { if (CoreLocal::get("msgrepeat") == 0) { CoreLocal::set("boxMsg", "<B>" . $total . " stock payment</B><BR>insert form<BR>press [enter] to endorse<P><FONT size='-1'>[clear] to cancel</FONT>"); $ret["main_frame"] = $my_url . "gui-modules/boxMsg2.php?endorse=stock&endorseAmt=" . $total; } } break; case '8005': if (CoreLocal::get("memberID") == 0) { $json['main_frame'] = $my_url . 'gui-modules/memlist.php'; } elseif (CoreLocal::get("isMember") == 0) { $json['output'] = DisplayLib::boxMsg(_("member discount not applicable"), '', false, DisplayLib::standardClearButton()); } elseif (CoreLocal::get("percentDiscount") > 0) { $json['output'] = DisplayLib::boxMsg(CoreLocal::get("percentDiscount") . "% discount already applied", '', false, DisplayLib::standardClearButton()); } break; } // magic plu, but other conditions not matched if ($json['main_frame'] === false && empty($json['output'])) { $json['output'] = DisplayLib::boxMsg($upc . "<br />is not a valid item", '', false, DisplayLib::standardClearButton()); } return $json; }
/** React to missing item @param $upc [string] UPC value @param $json [keyed array] formatted return value @return [keyed array] formatted return value The $json parameter and return value have the same format as Parser since this module interacts with input parsing. */ public function handle($upc, $json) { $opts = array('upc' => $upc, 'description' => 'BADSCAN'); TransRecord::add_log_record($opts); $json['output'] = DisplayLib::boxMsg(_('not a valid item'), _('UPC: ') . $upc, false, DisplayLib::standardClearButton()); return $json; }
function parse($str) { $ret = $this->default_json(); if ($str == "FNTL") { $ret['main_frame'] = MiscLib::base_url() . 'gui-modules/fsTotalConfirm.php'; } elseif ($str == "TETL") { $ret['main_frame'] = MiscLib::base_url() . 'gui-modules/requestInfo.php?class=Totals'; } elseif ($str == "FTTL") { PrehLib::finalttl(); } elseif ($str == "TL") { CoreLocal::set('End', 0); $chk = PrehLib::ttl(); if ($chk !== True) { $ret['main_frame'] = $chk; } } elseif ($str == "MTL") { $chk = PrehLib::omtr_ttl(); if ($chk !== True) { $ret['main_frame'] = $chk; } } elseif ($str == "WICTL") { $ttl = PrehLib::wicableTotal(); $ret['output'] = DisplayLib::boxMsg(_('WIC Total') . sprintf(': $%.2f', $ttl), '', true, DisplayLib::standardClearButton()); // return early since output has been set return $ret; } if (!$ret['main_frame']) { $ret['output'] = DisplayLib::lastpage(); $ret['redraw_footer'] = True; } return $ret; }
function check($str) { $this->ret = $this->default_json(); if (substr($str, -2) == "SD") { $strl = substr($str, 0, strlen($str) - 2); if (!is_numeric($strl)) { return False; } elseif (CoreLocal::get("tenderTotal") != 0) { $this->ret['output'] = DisplayLib::boxMsg(_("discount not applicable after tender"), '', false, DisplayLib::standardClearButton()); } elseif ($strl > 50) { $this->ret['output'] = DisplayLib::boxMsg(_("discount exceeds maximum"), '', false, DisplayLib::standardClearButton()); } elseif ($strl <= 0) { $this->ret['output'] = DisplayLib::boxMsg(_("discount must be greater than zero"), '', false, DisplayLib::standardClearButton()); } elseif ($strl <= 50 and $strl > 0) { $existingPD = CoreLocal::get("percentDiscount"); $stackablePD = $strl; $equivalentPD = $existingPD + $stackablePD; // sum discounts $this->ret = PrehLib::percentDiscount($equivalentPD, $this->ret); } else { return false; } return true; } return false; }
function parse($str) { $ret = $this->default_json(); PrehLib::chargeOk(); $memChargeCommitted = CoreLocal::get("availBal") - CoreLocal::get("memChargeTotal"); $title = _('Member #') . CoreLocal::get('memberID'); $msg = _("Current AR balance is ") . CoreLocal::get("balance") . "<br />" . _("Available AR balance is ") . CoreLocal::get("availBal"); $ret['output'] = DisplayLib::boxMsg($msg, $title, true, array_merge(array('Tender [Store Credit]' => 'parseWrapper(\'MI\');'), DisplayLib::standardClearButton())); return $ret; }
function parse($str) { if (CoreLocal::get("LastID") == 0) { $ret = $this->default_json(); $ret['output'] = DisplayLib::boxMsg(_("no transaction in progress"), '', false, DisplayLib::standardClearButton()); return $ret; } else { return $this->tender_out(""); } }
/** Check for errors @return True or an error message string */ public function errorCheck() { if (CoreLocal::get("fntlflag") == 0) { return DisplayLib::boxMsg(_("eligible amount must be totaled before foodstamp tender can be accepted"), '', false, array('Total [FS Total]' => 'parseWrapper(\'FNTL\');$(\'#reginput\').focus();', 'Dimiss [clear]' => 'parseWrapper(\'CL\');')); } elseif ($this->amount !== false && $this->amount > 0 && $this->amount > CoreLocal::get("fsEligible") + 0.005) { return DisplayLib::xboxMsg(_('Foodstamp tender cannot exceed eligible amount'), DisplayLib::standardClearButton()); } elseif ($this->amount !== false && $this->amount <= 0 && $this->amount < CoreLocal::get("fsEligible") - 0.005) { return DisplayLib::xboxMsg(_('Foodstamp return cannot exceed eligible amount' . $info), DisplayLib::standardClearButton()); } return true; }
function parse($str) { $ret = $this->default_json(); if (CoreLocal::get("memberID") == 0) { $ret['output'] = DisplayLib::boxMsg(_("Apply member number first"), _('No member selected'), false, array_merge(array('Member Search [ID]' => 'parseWrapper(\'ID\');'), DisplayLib::standardClearButton())); } else { $plugin_info = new VirtualCoupon(); $ret['main_frame'] = $plugin_info->pluginUrl() . '/VirtCoupDisplay.php'; } return $ret; }
private function overlayKeys($number) { $db = Database::pDataConnect(); $my_keys = array(); if ($db->table_exists('QuickLookups')) { $prep = $db->prepare(' SELECT label, action FROM QuickLookups WHERE lookupSet = ? ORDER BY sequence'); $res = $db->execute($prep, array($number)); while ($row = $db->fetch_row($res)) { $my_keys[] = new quickkey($row['label'], $row['action']); } } if (count($my_keys) == 0) { include dirname(__FILE__) . '/quickkeys/keys/' . $number . '.php'; } if (count($my_keys) == 0) { return DisplayLib::boxMsg('Menu not found', '', false, DisplayLib::standardClearButton()); } $clearButton = false; $ret = ''; for ($i = 0; $i < count($my_keys); $i++) { if ($i % 3 == 0) { if ($i != 0) { $ret .= ' </div>'; } $ret .= '<div class="qkRow">'; } $ret .= sprintf(' <div class="qkBox"> <div id="qkDiv%d"> <button type="button" class="quick_button pos-button coloredBorder" onclick="$(\'#reginput\').val($(\'#reginput\').val()+\'%s\');submitWrapper();"> %s </button> </div> </div>', $i, $my_keys[$i]->output_text, $my_keys[$i]->title); } if (!$clearButton) { $ret .= '<div class="qkBox"> <div> <button type="button" class="quick_button pos-button errorColoredArea" onclick="$(\'#reginput\').val(\'CL\');submitWrapper();"> Clear <span class="smaller">[clear]</span> </button> </div> </div>'; } $ret .= '</div>'; return $ret; }
function parse($str) { $ret = $this->default_json(); if ($str == "cdInvalid") { $ret['output'] = DisplayLib::boxMsg(CoreLocal::get("casediscount") . _("% case discount invalid"), '', false, DisplayLib::standardClearButton()); } elseif ($str == "cdStaffNA") { $ret['output'] = DisplayLib::boxMsg(_("case discount not applicable to staff"), '', false, DisplayLib::standardClearButton()); } elseif ($str == "cdSSINA") { $ret['output'] = DisplayLib::boxMsg(_("hit 10% key to apply case discount for member") . " " . CoreLocal::get("memberID"), '', false, DisplayLib::standardClearButton()); } return $ret; }
/** Check for errors @return True or an error message string */ public function errorCheck() { if (MiscLib::truncate2(CoreLocal::get("amtdue")) < MiscLib::truncate2($this->amount)) { return DisplayLib::xboxMsg(_("store transfer exceeds purchase amount"), DisplayLib::standardClearButton()); } $db = Database::pDataConnect(); $query = 'SELECT chargeOk FROM custdata WHERE chargeOk=1 AND CardNo=' . CoreLocal::get('memberID'); $result = $db->query($query); if ($db->num_rows($result) == 0) { return DisplayLib::xboxMsg(_("member cannot make transfers"), DisplayLib::standardClearButton()); } return true; }
function parse($str) { $ret = $this->default_json(); $query = "select upc,description,VolSpecial,quantity,\n total,discount,memDiscount,discountable,\n unitPrice,scale,foodstamp,voided,discounttype,\n trans_type,trans_status,department,regPrice,\n tax,volume,volDiscType\n from localtemptrans where \n trans_id = " . CoreLocal::get("currentid"); $connection = Database::tDataConnect(); $result = $connection->query($query); $num_rows = $connection->num_rows($result); if ($num_rows > 0) { $row = $connection->fetch_array($result); $strUPC = $row["upc"]; $strDescription = $row["description"]; $dblVolSpecial = $row["VolSpecial"]; $dblquantity = -0.5 * $row["quantity"]; $dblTotal = MiscLib::truncate2(-1 * 0.5 * $row["total"]); // invoked truncate2 rounding function to fix half-penny errors apbw 3/7/05 $strCardNo = CoreLocal::get("memberID"); $dblDiscount = $row["discount"]; $dblmemDiscount = $row["memDiscount"]; $intDiscountable = $row["discountable"]; $dblUnitPrice = $row["unitPrice"]; $intScale = MiscLib::nullwrap($row["scale"]); if ($row["foodstamp"] != 0) { $intFoodStamp = 1; } else { $intFoodStamp = 0; } $intdiscounttype = MiscLib::nullwrap($row["discounttype"]); if ($row["voided"] == 20) { $ret['output'] = DisplayLib::boxMsg(_("Discount already taken"), '', false, DisplayLib::standardClearButton()); } elseif ($row["trans_type"] == "T" or $row["trans_status"] == "D" or $row["trans_status"] == "V" or $row["trans_status"] == "C") { $ret['output'] = DisplayLib::boxMsg(_("Item cannot be discounted"), '', false, DisplayLib::standardClearButton()); } elseif (strncasecmp($strDescription, "Club Card", 9) == 0) { //----- edited by abpw 2/15/05 ----- $ret['output'] = DisplayLib::boxMsg(_("Item cannot be discounted"), '', false, DisplayLib::standardClearButton()); } elseif (CoreLocal::get("tenderTotal") < 0 and $intFoodStamp == 1 and -1 * $dblTotal > CoreLocal::get("fsEligible")) { $ret['output'] = DisplayLib::boxMsg(_("Item already paid for"), '', false, DisplayLib::standardClearButton()); } elseif (CoreLocal::get("tenderTotal") < 0 and -1 * $dblTotal > CoreLocal::get("runningTotal") - CoreLocal::get("taxTotal")) { $ret['output'] = DisplayLib::boxMsg(_("Item already paid for"), '', false, DisplayLib::standardClearButton()); } else { // --- added partial item desc to club card description - apbw 2/15/05 --- TransRecord::addRecord(array('upc' => $strUPC, 'description' => "Club Card: " . substr($strDescription, 0, 19), 'trans_type' => "I", 'trans_status' => "J", 'department' => $row["department"], 'quantity' => $dblquantity, 'unitPrice' => $dblUnitPrice, 'total' => $dblTotal, 'regPrice' => 0.5 * $row["regPrice"], 'scale' => $intScale, 'tax' => $row["tax"], 'foodstamp' => $intFoodStamp, 'discount' => $dblDiscount, 'memDiscount' => $dblmemDiscount, 'discountable' => $intDiscountable, 'discounttype' => $intdiscounttype, 'ItemQtty' => $dblquantity, 'volDiscType' => $row["volDiscType"], 'volume' => $row["volume"], 'VolSpecial' => $dblVolSpecial)); $update = "update localtemptrans set voided = 20 where trans_id = " . CoreLocal::get("currentid"); $connection = Database::tDataConnect(); $connection->query($update); CoreLocal::set("TTLflag", 0); CoreLocal::set("TTLRequested", 0); $ret['output'] = DisplayLib::lastpage(); } } return $ret; }
public function handle($upc, $json) { $db = Database::pDataConnect(); $query = "select card_no from memberCards where upc='{$upc}'"; $result = $db->query($query); if ($db->num_rows($result) < 1) { $json['output'] = DisplayLib::boxMsg(_("Card not assigned"), '', false, DisplayLib::standardClearButton()); return $json; } $row = $db->fetch_array($result); CoreLocal::set("memberCardUsed", 1); $json = PrehLib::memberID($row[0]); return $json; }
function parse($str) { $ret = $this->default_json(); $left = substr($str, 0, strlen($str) - 2); if ($left == "") { $left = 1; } if (strlen($left) > 4) { $ret['output'] = DisplayLib::boxMsg(MiscLib::truncate2($left / 100) . _(" tare not supported"), _('Invalid Tare'), false, DisplayLib::standardClearButton()); } elseif ($left / 100 > CoreLocal::get("weight") && CoreLocal::get("weight") > 0) { $ret['output'] = DisplayLib::boxMsg(_("Tare cannot be") . "<br />" . _("greater than item weight"), _('Excess Tare'), false, DisplayLib::standardClearButton()); } else { TransRecord::addTare($left); $ret['output'] = DisplayLib::lastpage(); } return $ret; }
public function parse($str) { $multiplier = strlen($str) > 1 ? substr($str, 1) : 1; $peek = PrehLib::peekItem(true, CoreLocal::get('currentid')); $fp = fopen('/tmp/peek', 'a'); if ($peek && $peek['trans_type'] == 'I' && $peek['trans_status'] == '') { $upcP = new UPC(); CoreLocal::set('quantity', $multiplier); CoreLocal::set('multiple', 1); $ret = $upcP->parse($peek['upc']); return $ret; } else { $json = $this->default_json(); $json['output'] = DisplayLib::boxMsg(_('product cannot be repeated'), _('Ineligible line'), false, DisplayLib::standardClearButton()); return $json; } }
function parse($str) { $ret = $this->default_json(); if (CoreLocal::get('isMember') !== 1) { $ret['output'] = DisplayLib::boxMsg(_("Apply member number first"), _('No member selected'), false, array_merge(array('Member Search [ID]' => 'parseWrapper(\'ID\');'), DisplayLib::standardClearButton())); return $ret; } elseif (CoreLocal::get('NeedDiscountFlag') == 1) { $ret['output'] = DisplayLib::boxMsg(_("discount already applied"), '', false, DisplayLib::standardClearButton()); return $ret; } else { CoreLocal::set('NeedDiscountFlag', 1); $NBDisc = CoreLocal::get('needBasedPercent') * 100; DiscountModule::updateDiscount(new DiscountModule($NBDisc, 'NeedBasedDiscount')); $ret['output'] = DisplayLib::lastpage(); $ret['redraw_footer'] = true; return $ret; } }
function parse($str) { $ret = $this->default_json(); // this is the currently selected item $transID = CoreLocal::get("currentid"); $row = PrehLib::peekItem(true, $transID); if ($row === false) { // this shouldn't happen unless there's some weird session problem $ret['output'] = DisplayLib::boxMsg(_("Item not found"), '', false, DisplayLib::standardClearButton()); } else { if ($row['trans_type'] != 'I' && $row['trans_type'] != 'D') { // only items & open rings are discountable $ret['output'] = DisplayLib::boxMsg(_("Line is not discountable"), '', false, DisplayLib::standardClearButton()); } elseif ($row['discounttype'] != 0) { // for simplicity, sale items cannot be discounted // this also prevents using this function more than // once on a single item $ret['output'] = DisplayLib::boxMsg(_("Item already discounted"), '', false, DisplayLib::standardClearButton()); } else { // discount is simply the total times the // non-member discount percentage // total is discounted immediately using // the non-member percentage // memDiscount is the difference between total // member discount and the non-member discount // since the non-member discount is applied // immediately // setting discounttype=2 makes the member discount // apply when a [valid] member number is entered $discQ = sprintf("UPDATE localtemptrans SET\n discount=(regPrice * quantity * %f), \n total=(total-(regPrice*quantity*%f)),\n memDiscount=((regPrice*quantity*%f) - (regPrice*quantity*%f)),\n discounttype=2\n WHERE trans_id=%d", CoreLocal::get("LineItemDiscountNonMem"), CoreLocal::get("LineItemDiscountNonMem"), CoreLocal::get("LineItemDiscountMem"), CoreLocal::get("LineItemDiscountNonMem"), $transID); $dbc = Database::tDataConnect(); $discR = $dbc->query($discQ); // add notification line for nonMem discount TransRecord::adddiscount($row['regPrice'] * $row['quantity'] * CoreLocal::get("LineItemDiscountNonMem"), $row['department']); // footer should be redrawn since savings and totals // have changed. Output is the list of items $ret['redraw_footer'] = true; $ret['output'] = DisplayLib::lastpage(); } } return $ret; }
/** Add a percent discount notification @param $strl discount percentage @param $json keyed array @return An array see Parser::default_json() @deprecated Use discountnotify() instead. This just adds hard-coded percentages and PLUs that likely aren't applicable anywhere but the Wedge. */ public static function percentDiscount($strl, $json = array()) { if ($strl == 10.01) { $strl = 10; } if (!is_numeric($strl) || $strl > 100 || $strl < 0) { $json['output'] = DisplayLib::boxMsg(_("discount invalid"), '', false, DisplayLib::standardClearButton()); } else { if ($strl != 0) { TransRecord::discountnotify($strl); } $dbc = Database::tDataConnect(); $dbc->query("update localtemptrans set percentDiscount = " . $strl); $chk = self::ttl(); if ($chk !== true) { $json['main_frame'] = $chk; } $json['output'] = DisplayLib::lastpage(); } return $json; }
public function testCouponCode() { if (!class_exists('lttLib')) { include dirname(__FILE__) . '/lttLib.php'; } $cc = new CouponCode(); $out = $cc->handle('0051234512345', array()); $expected_error = DisplayLib::boxMsg(_("product not found") . "<br />" . _("in transaction"), '', true, DisplayLib::standardClearButton()); $this->assertArrayHasKey('output', $out); $this->assertEquals($out['output'], $expected_error); lttLib::clear(); $out = $cc->handle('0051234599210', array()); $record = lttLib::genericRecord(); $record['upc'] = '0051234599210'; $record['description'] = ' * Manufacturers Coupon'; $record['trans_type'] = 'I'; $record['trans_subtype'] = 'CP'; $record['trans_status'] = 'C'; $record['quantity'] = 1; $record['ItemQtty'] = 1; $record['unitPrice'] = -0.1; $record['total'] = -0.1; $record['regPrice'] = -0.1; lttLib::verifyRecord(1, $record, $this); lttLib::clear(); $db = Database::tDataConnect(); $db->query('TRUNCATE TABLE couponApplied'); $u = new UPC(); $u->parse('0001101312028'); $out = $cc->handle('0051101399901', array()); $record = lttLib::genericRecord(); $record['upc'] = '0051101399901'; $record['description'] = ' * Manufacturers Coupon'; $record['trans_type'] = 'I'; $record['trans_subtype'] = 'CP'; $record['trans_status'] = 'C'; $record['department'] = 181; $record['quantity'] = 1; $record['ItemQtty'] = 1; $record['unitPrice'] = -4.59; $record['total'] = -4.59; $record['regPrice'] = -4.59; lttLib::verifyRecord(2, $record, $this); }
function discountupc($upc, $item_num = -1, $pd = 0) { $lastpageflag = 1; $deliflag = 0; $quantity = 0; if (strpos($upc, "*") && (strpos($upc, "**") || strpos($upc, "*") == 0 || strpos($upc, "*") == strlen($upc) - 1)) { $upc = "stop"; } elseif (strpos($upc, "*")) { $voidupc = explode("*", $upc); if (!is_numeric($voidupc[0])) { $upc = "stop"; } else { $quantity = $voidupc[0]; $upc = $voidupc[1]; $weight = 0; } } elseif (!is_numeric($upc) && !strpos($upc, "DP")) { $upc = "stop"; } else { $quantity = 1; $weight = CoreLocal::get("weight"); } $scaleprice = 0; if (is_numeric($upc)) { $upc = substr("0000000000000" . $upc, -13); if (substr($upc, 0, 3) == "002" && substr($upc, -5) != "00000") { $scaleprice = substr($upc, 10, 4) / 100; $upc = substr($upc, 0, 8) . "0000"; $deliflag = 1; } elseif (substr($upc, 0, 3) == "002" && substr($upc, -5) == "00000") { $deliflag = 1; } } if ($upc == "stop") { return DisplayLib::inputUnknown(); } $db = Database::tDataConnect(); $query = "select sum(ItemQtty) as voidable, sum(quantity) as vquantity, max(scale) as scale, " . "max(volDiscType) as volDiscType from localtemptrans where upc = '" . $upc . "' and unitPrice = " . $scaleprice . " and discounttype <> 3 group by upc"; $result = $db->query($query); $num_rows = $db->num_rows($result); if ($num_rows == 0) { return DisplayLib::boxMsg(_("Item not found: ") . $upc, '', false, DisplayLib::standardClearButton()); } $row = $db->fetch_array($result); if ($row["scale"] == 1 && $weight > 0) { $quantity = $weight - CoreLocal::get("tare"); CoreLocal::set("tare", 0); } $volDiscType = $row["volDiscType"]; $voidable = MiscLib::nullwrap($row["voidable"]); $VolSpecial = 0; $volume = 0; $scale = MiscLib::nullwrap($row["scale"]); //----------------------Void Item------------------ $query_upc = "select ItemQtty,foodstamp,discounttype,mixMatch,cost,\n numflag,charflag,unitPrice,discounttype,regPrice,discount,\n memDiscount,discountable,description,trans_type,trans_subtype,\n department,tax,VolSpecial\n from localtemptrans where upc = '" . $upc . "' and unitPrice = " . $scaleprice . " and trans_id={$item_num}"; $result = $db->query($query_upc); $row = $db->fetch_array($result); $ItemQtty = $row["ItemQtty"]; $foodstamp = MiscLib::nullwrap($row["foodstamp"]); $discounttype = MiscLib::nullwrap($row["discounttype"]); $mixMatch = MiscLib::nullwrap($row["mixMatch"]); $cost = isset($row["cost"]) ? -1 * $row["cost"] : 0; $numflag = isset($row["numflag"]) ? $row["numflag"] : 0; $charflag = isset($row["charflag"]) ? $row["charflag"] : 0; $unitPrice = $row["unitPrice"]; if (CoreLocal::get("isMember") != 1 && $row["discounttype"] == 2 || CoreLocal::get("isStaff") == 0 && $row["discounttype"] == 4) { $unitPrice = $row["regPrice"]; } elseif ((CoreLocal::get("isMember") == 1 && $row["discounttype"] == 2 || CoreLocal::get("isStaff") != 0 && $row["discounttype"] == 4) && $row["unitPrice"] == $row["regPrice"]) { $db_p = Database::pDataConnect(); $query_p = "select special_price from products where upc = '" . $upc . "'"; $result_p = $db_p->query($query_p); $row_p = $db_p->fetch_array($result_p); $unitPrice = $row_p["special_price"]; } $discount = -1 * $row["discount"]; $memDiscount = -1 * $row["memDiscount"]; $discountable = $row["discountable"]; $CardNo = CoreLocal::get("memberID"); $discounttype = MiscLib::nullwrap($row["discounttype"]); if ($discounttype == 3) { $quantity = -1 * $ItemQtty; } elseif ($quantity != 0) { TransRecord::addRecord(array('upc' => $upc, 'description' => $row["description"], 'trans_type' => $row["trans_type"], 'trans_subtype' => $row["trans_subtype"], 'trans_status' => "V", 'department' => $row["department"], 'quantity' => $quantity, 'unitPrice' => $unitPrice, 'total' => $total, 'regPrice' => $row["regPrice"], 'scale' => $scale, 'tax' => $row["tax"], 'foodstamp' => $foodstamp, 'discount' => $discount, 'memDiscount' => $memDiscount, 'discountable' => $discountable, 'discounttype' => $discounttype, 'quantity' => $quantity, 'volDiscType' => $volDiscType, 'volume' => $volume, 'VolSpecial' => $VolSpecial, 'mixMatch' => $mixMatch, 'voided' => 1, 'cost' => $cost, 'numflag' => $numflag, 'charflag' => $charflag)); if ($row["trans_type"] != "T") { CoreLocal::set("ttlflag", 0); } $db = Database::pDataConnect(); $chk = $db->query("SELECT deposit FROM products WHERE upc='{$upc}'"); if ($db->num_rows($chk) > 0) { $dpt = array_pop($db->fetch_row($chk)); if ($dpt > 0) { $dupc = (int) $dpt; return $this->voidupc(-1 * $quantity . "*" . $dupc, True); } } } return ""; }
function upcscanned($entered) { $my_url = MiscLib::base_url(); $ret = $this->default_json(); /* force cashiers to enter a comment on refunds */ if (CoreLocal::get("refund") == 1 && CoreLocal::get("refundComment") == "") { $ret['udpmsg'] = 'twoPairs'; if (CoreLocal::get("SecurityRefund") > 20) { $ret['main_frame'] = $my_url . "gui-modules/adminlogin.php?class=RefundAdminLogin"; } else { $ret['main_frame'] = $my_url . 'gui-modules/refundComment.php'; } CoreLocal::set("refundComment", CoreLocal::get("strEntered")); return $ret; } if (CoreLocal::get('itemPD') > 0 && CoreLocal::get('SecurityLineItemDiscount') == 30 && CoreLocal::get('msgrepeat') == 0) { $ret['main_frame'] = $my_url . "gui-modules/adminlogin.php?class=LineItemDiscountAdminLogin"; return $ret; } /** 11Sep14 Andy Disabled until keypress double form submission is fixed on paycard confirmation screen. Depending on sequence can case flag to be raised, cleared, and re-raised leading to spurrious error notifications */ if (false && CoreLocal::get('paycardTendered')) { if (CoreLocal::get('msgrepeat') == 0 || CoreLocal::get('lastRepeat') != 'paycardAlreadyApplied') { CoreLocal::set('boxMsg', 'Card already tendered<br /> Confirm adding more items'); CoreLocal::set('lastRepeat', 'paycardAlreadyApplied'); $ret['main_frame'] = $my_url . 'gui-modules/boxMsg2.php'; return $ret; } else { if (CoreLocal::get('lastRepeat') == 'paycardAlreadyApplied') { CoreLocal::set('lastRepeat', ''); CoreLocal::set('paycardTendered', false); } } } $upc = $this->sanitizeUPC($entered); $quantity = CoreLocal::get("quantity"); if (CoreLocal::get("quantity") == 0 && CoreLocal::get("multiple") == 0) { $quantity = 1; } list($scaleStickerItem, $scalepriceUPC, $scalepricEAN) = $this->rewriteScaleSticker($upc); $db = Database::pDataConnect(); $table = $db->table_definition('products'); $query = "SELECT inUse,upc,description,normal_price,scale,deposit,\n qttyEnforced,department,local,cost,tax,foodstamp,discount,\n discounttype,specialpricemethod,special_price,groupprice,\n pricemethod,quantity,specialgroupprice,specialquantity,\n mixmatchcode,idEnforced,tareweight,scaleprice"; // New column 16Apr14 if (isset($table['line_item_discountable'])) { $query .= ', line_item_discountable'; } else { $query .= ', 1 AS line_item_discountable'; } // New column 16Apr14 if (isset($table['formatted_name'])) { $query .= ', formatted_name'; } else { $query .= ', \'\' AS formatted_name'; } // New column 25Nov14 if (isset($table['special_limit'])) { $query .= ', special_limit'; } else { $query .= ', 0 AS special_limit'; } $query .= " FROM products WHERE upc = '" . $upc . "'"; $result = $db->query($query); $num_rows = $db->num_rows($result); /* check for special upcs that aren't really products */ if ($num_rows == 0) { $objs = CoreLocal::get("SpecialUpcClasses"); foreach ($objs as $class_name) { $instance = new $class_name(); if ($instance->isSpecial($upc)) { return $instance->handle($upc, $ret); } } // no match; not a product, not special if ($db->table_exists('IgnoredBarcodes')) { // lookup UPC in tabe of ignored barcodes // this just suppresses any error message from // coming back $query = 'SELECT upc FROM IgnoredBarcodes WHERE upc=\'' . $upc . "'"; $result = $db->query($query); if ($result && $db->num_rows($result)) { return $this->default_json(); } } $handler = CoreLocal::get('ItemNotFound'); if ($handler === '' || !class_exists($handler)) { $handler = 'ItemNotFound'; } $obj = new $handler(); $ret = $obj->handle($upc, $ret); return $ret; } /* product exists BEGIN error checking round #1 */ $row = $db->fetch_array($result); /** If formatted_name is present, copy it directly over products.description. This way nothing further down the process has to worry about the distinction between two potential naming fields. */ if ($row['formatted_name'] != '') { $row['description'] = $row['formatted_name']; } /* Implementation of inUse flag * if the flag is not set, display a warning dialog noting this * and allowing the sale to be confirmed or canceled */ if ($row["inUse"] == 0) { TransRecord::addLogRecord(array('upc' => $row['upc'], 'description' => $row['description'], 'department' => $row['department'], 'charflag' => 'IU')); } /** Apply special department handlers based on item's department */ $deptmods = CoreLocal::get('SpecialDeptMap'); if (!is_array($deptmods) && $db->table_exists('SpecialDeptMap')) { $model = new \COREPOS\pos\lib\models\op\SpecialDeptMapModel($db); $deptmods = $model->buildMap(); CoreLocal::set('SpecialDeptMap', $deptmods); } if (is_array($deptmods) && isset($deptmods[$row['department']])) { foreach ($deptmods[$row['department']] as $mod) { $obj = new $mod(); $ret = $obj->handle($row['department'], $row['normal_price'], $ret); if ($ret['main_frame']) { return $ret; } } } /** Detect if a by-weight item has the same weight as the last by-weight item. This can indicate a stuck scale. The giant if determines whether the item is scalable, that we know the weight, and that we know the previous weight (lastWeight) Pre-weighed items (upc starts with 002) are ignored because they're not weighed here. Scalable items that cost one cent are ignored as a special case; they're normally entered by keying a quantity multiplier */ if ($num_rows > 0 && $row['scale'] == 1 && CoreLocal::get("lastWeight") > 0 && CoreLocal::get("weight") > 0 && abs(CoreLocal::get("weight") - CoreLocal::get("lastWeight")) < 0.0005 && !$scaleStickerItem && abs($row['normal_price']) > 0.01) { if (CoreLocal::get('msgrepeat') == 0) { CoreLocal::set("strEntered", $row["upc"]); CoreLocal::set("boxMsg", "<b>Same weight as last item</b>"); CoreLocal::set('boxMsgButtons', array('Confirm Weight [enter]' => '$(\'#reginput\').val(\'\');submitWrapper();', 'Cancel [clear]' => '$(\'#reginput\').val(\'CL\');submitWrapper();')); $ret['main_frame'] = $my_url . "gui-modules/boxMsg2.php?quiet=1"; return $ret; } } if ($row["idEnforced"] > 0) { $restrictQ = "SELECT upc,dept_ID FROM dateRestrict WHERE\n ( upc='{$row['upc']}' AND\n ( " . $db->datediff($db->now(), 'restrict_date') . "=0 OR\n " . $db->dayofweek($db->now()) . "=restrict_dow\n ) AND\n ( (restrict_start IS NULL AND restrict_end IS NULL) OR\n " . $db->curtime() . " BETWEEN restrict_start AND restrict_end\n )\n ) OR \n ( dept_ID='{$row['department']}' AND\n ( " . $db->datediff($db->now(), 'restrict_date') . "=0 OR\n " . $db->dayofweek($db->now()) . "=restrict_dow\n ) AND\n ( (restrict_start IS NULL AND restrict_end IS NULL) OR\n " . $db->curtime() . " BETWEEN restrict_start AND restrict_end\n )\n )"; $restrictR = $db->query($restrictQ); if ($db->num_rows($restrictR) > 0) { $ret['output'] = DisplayLib::boxMsg(_('product cannot be sold right now'), _('Date Restriction'), false, DisplayLib::standardClearButton()); return $ret; } list($bad_age, $ret) = PrehLib::ageCheck($row['idEnforced'], $ret); if ($bad_age === true) { return $ret; } } /** Apply automatic tare weight */ if ($row['tareweight'] > 0) { $peek = PrehLib::peekItem(); if (strstr($peek, "** Tare Weight") === False) { TransRecord::addTare($row['tareweight'] * 100); } } elseif ($row['scale'] != 0 && !CoreLocal::get("tare") && Plugin::isEnabled('PromptForTare') && !CoreLocal::get("tarezero")) { $ret['main_frame'] = $my_url . 'plugins/PromptForTare/TarePromptInputPage.php?class=UPC&item=' . $entered; return $ret; } else { CoreLocal::set('tarezero', False); } /* sanity check - ridiculous price (can break db column if it doesn't fit */ if (strlen($row["normal_price"]) > 8) { $ret['output'] = DisplayLib::boxMsg($upc . '<br />' . _("Claims to be more than \$100,000"), _('Invalid Item'), false, DisplayLib::standardClearButton()); return $ret; } $scale = $row["scale"] == 0 ? 0 : 1; $qttyEnforced = $row["qttyEnforced"]; /* use scaleprice bit column to indicate whether values should be interpretted as UPC or EAN */ $scaleprice = $row['scaleprice'] == 0 ? $scalepriceUPC : $scalepriceEAN; /* need a weight with this item retry the UPC in a few milliseconds and see */ if ($scale != 0 && CoreLocal::get("weight") == 0 && $qttyEnforced == 0 && CoreLocal::get("quantity") == 0 && !$scaleStickerItem) { CoreLocal::set("SNR", CoreLocal::get('strEntered')); $ret['output'] = DisplayLib::boxMsg(_("please put item on scale"), 'Weighed Item', true, DisplayLib::standardClearButton()); return $ret; } /* quantity required for this item. Send to entry page if one wasn't provided */ if ($qttyEnforced == 1 && CoreLocal::get("multiple") == 0 && (CoreLocal::get("msgrepeat" == 0) || CoreLocal::get('qttyvalid') == 0)) { $ret['main_frame'] = $my_url . 'gui-modules/QuantityEntryPage.php' . '?entered-item=' . CoreLocal::get('strEntered') . '&qty-mode=' . $scale; return $ret; } /* got a scale weight, make sure the tare is valid */ if ($scale != 0 && !$scaleStickerItem) { $quantity = CoreLocal::get("weight") - CoreLocal::get("tare"); if (CoreLocal::get("quantity") != 0) { $quantity = CoreLocal::get("quantity") - CoreLocal::get("tare"); } if ($quantity <= 0) { $ret['output'] = DisplayLib::boxMsg(_("item weight must be greater than tare weight"), _('Invalid Weight'), false, DisplayLib::standardClearButton()); return $ret; } CoreLocal::set("tare", 0); } /* non-scale items need integer quantities */ if ($row["scale"] == 0 && (int) CoreLocal::get("quantity") != CoreLocal::get("quantity")) { $ret['output'] = DisplayLib::boxMsg(_("fractional quantity cannot be accepted for this item"), _('Invalid Quantity'), false, DisplayLib::standardClearButton()); return $ret; } /* wedge I assume I don't like this being hard-coded, but since these UPCs are entries in products they can't go in a SpecialUPC object (unless SpecialUPC checks take place on every scan, but that's more overhead than I want on such a common operation */ if ($upc == "0000000008010" && CoreLocal::get("msgrepeat") == 0) { CoreLocal::set("boxMsg", "<b>" . $total . " gift certificate</b><br />\n " . _("insert document")); CoreLocal::set('boxMsgButtons', array('Endorse [enter]' => '$(\'#reginput\').val(\'\');submitWrapper();', 'Cancel [clear]' => '$(\'#reginput\').val(\'CL\');submitWrapper();')); $ret["main_frame"] = $my_url . "gui-modules/boxMsg2.php?endorse=giftcert&endorseAmt=" . $total; return $ret; } /* wedge I assume see 0000000008010 above */ if ($upc == "0000000008011" && CoreLocal::get("msgrepeat") == 0) { CoreLocal::set("boxMsg", "<b>" . $total . " class registration</b><br />\n " . _("insert form")); CoreLocal::set('boxMsgButtons', array('Endorse [enter]' => '$(\'#reginput\').val(\'\');submitWrapper();', 'Cancel [clear]' => '$(\'#reginput\').val(\'CL\');submitWrapper();')); $ret["main_frame"] = $my_url . "gui-modules/boxMsg2.php?endorse=classreg&endorseAmt=" . $total; return $ret; } /* END error checking round #1 */ // wfc uses deposit field to link another upc if (isset($row["deposit"]) && $row["deposit"] > 0) { $dupc = (int) $row["deposit"]; $this->addDeposit($dupc); } $upc = $row["upc"]; $row['numflag'] = isset($row["local"]) ? $row["local"] : 0; $row['description'] = str_replace("'", "", $row['description']); list($tax, $foodstamp, $discountable) = PrehLib::applyToggles($row['tax'], $row['foodstamp'], $row['discount']); $row['tax'] = $tax; $row['foodstamp'] = $foodstamp; $row['discount'] = $discountable; /** Enforce per-transaction sale limits */ if ($row['special_limit'] > 0) { $appliedQ = "\n SELECT SUM(quantity) AS saleQty\n FROM " . CoreLocal::get('tDatabase') . $db->sep() . "localtemptrans\n WHERE discounttype <> 0\n AND (\n upc='{$row['upc']}'\n OR (mixMatch='{$row['mixmatchcode']}' AND mixMatch<>''\n AND mixMatch<>'0' AND mixMatch IS NOT NULL)\n )"; $appliedR = $db->query($appliedQ); if ($appliedR && $db->num_rows($appliedR)) { $appliedW = $db->fetch_row($appliedR); if ($appliedW['saleQty'] + $quantity > $row['special_limit']) { $row['discounttype'] = 0; $row['special_price'] = 0; $row['specialpricemethod'] = 0; $row['specialquantity'] = 0; $row['specialgroupprice'] = 0; } } } /* BEGIN: figure out discounts by type */ /* get discount object CORE reserves values 0 through 63 in DiscountType::$MAP for default options. Additional discounts provided by plugins can use values 64 through 127. Because the DiscountTypeClasses array is zero-indexed, subtract 64 as an offset */ $discounttype = MiscLib::nullwrap($row["discounttype"]); $DiscountObject = null; $DTClasses = CoreLocal::get("DiscountTypeClasses"); if ($row['discounttype'] < 64 && isset(DiscountType::$MAP[$row['discounttype']])) { $class = DiscountType::$MAP[$row['discounttype']]; $DiscountObject = new $class(); } else { if ($row['discounttype'] >= 64 && isset($DTClasses[$row['discounttype'] - 64])) { $class = $DTClasses[$row['discounttype'] - 64]; $DiscountObject = new $class(); } else { // If the requested discounttype isn't available, // fallback to normal pricing. Debatable whether // this should be a hard error. $DiscountObject = new NormalPricing(); } } /* add in sticker price and calculate a quantity if the item is stickered, scaled, and on sale. otherwise, if the item is sticked, scaled, and not on sale but has a non-zero price attempt to calculate a quantity. this makes the quantity field more consistent for reporting purposes. however, if the calculated quantity somehow introduces a rounding error fall back to the sticker's price. for non-sale items, the price the customer pays needs to match the sticker price exactly. items that are not scaled do not need a fractional quantity and items that do not have a normal_price assigned cannot calculate a proper quantity. */ if ($scaleStickerItem) { if ($DiscountObject->isSale() && $scale == 1 && $row['normal_price'] != 0) { $quantity = MiscLib::truncate2($scaleprice / $row["normal_price"]); } else { if ($scale == 1 && $row['normal_price'] != 0) { $quantity = MiscLib::truncate2($scaleprice / $row["normal_price"]); if (round($scaleprice, 2) != round($quantity * $row['normal_price'], 2)) { $quantity = 1.0; $row['normal_price'] = $scaleprice; } } else { $row['normal_price'] = $scaleprice; } } } /* END: figure out discounts by type */ /* get price method object & add item CORE reserves values 0 through 99 in PriceMethod::$MAP for default methods. Additional methods provided by plugins can use values 100 and up. Because the PriceMethodClasses array is zero-indexed, subtract 100 as an offset */ $pricemethod = MiscLib::nullwrap($row["pricemethod"]); if ($DiscountObject->isSale()) { $pricemethod = MiscLib::nullwrap($row["specialpricemethod"]); } $PMClasses = CoreLocal::get("PriceMethodClasses"); $PriceMethodObject = null; $row['trans_subtype'] = $this->status; if ($pricemethod < 100 && isset(PriceMethod::$MAP[$pricemethod])) { $class = PriceMethod::$MAP[$pricemethod]; $PriceMethodObject = new $class(); } else { if ($pricemethod >= 100 && isset($PMClasses[$pricemethod - 100])) { $class = $PMClasses[$pricemethod - 100]; $PriceMethodObject = new $class(); } else { $PriceMethodObject = new BasicPM(); } } // prefetch: otherwise object members // pass out of scope in addItem() $prefetch = $DiscountObject->priceInfo($row, $quantity); $added = $PriceMethodObject->addItem($row, $quantity, $DiscountObject); if (!$added) { $ret['output'] = DisplayLib::boxMsg($PriceMethodObject->errorInfo(), '', false, DisplayLib::standardClearButton()); return $ret; } /* add discount notifications lines, if applicable */ $DiscountObject->addDiscountLine(); // cleanup, reset flags and beep if ($quantity != 0) { CoreLocal::set("msgrepeat", 0); CoreLocal::set("qttyvalid", 0); $ret['udpmsg'] = 'goodBeep'; } /* reset various flags and variables */ if (CoreLocal::get("tare") != 0) { CoreLocal::set("tare", 0); } CoreLocal::set("ttlflag", 0); CoreLocal::set("fntlflag", 0); CoreLocal::set("quantity", 0); CoreLocal::set("itemPD", 0); Database::setglobalflags(0); /* output item list, update totals footer */ $ret['redraw_footer'] = True; $ret['output'] = DisplayLib::lastpage(); if ($prefetch['unitPrice'] == 0 && $discounttype == 0) { $ret['main_frame'] = $my_url . 'gui-modules/priceOverride.php'; } return $ret; }
/** Void the given UPC @param $upc [string] upc to void. Optionally including quantity and asterisk @param $item_num [int] trans_id of record to void. Optional. @param $json parser return value structure */ public function voidupc($upc, $json, $item_num = -1) { $lastpageflag = 1; $deliflag = false; $quantity = 0; /** If UPC contains an asterisk, extract quantity and validate input. Otherwise use quantity 1. */ if (strstr($upc, '*')) { list($quantity, $upc) = explode('*', $upc, 2); if ($quantity === '' || $upc === '' || !is_numeric($quantity) || !is_numeric($upc)) { $json['output'] = DisplayLib::inputUnknown(); return $json; } else { $weight = 0; } } else { $quantity = 1; $weight = CoreLocal::get("weight"); } $scaleprice = 0; if (is_numeric($upc)) { $upc = substr("0000000000000" . $upc, -13); if (substr($upc, 0, 3) == "002" && substr($upc, -5) != "00000") { $scaleprice = substr($upc, 10, 4) / 100; $upc = substr($upc, 0, 8) . "0000"; $deliflag = true; } else { if (substr($upc, 0, 3) == "002" && substr($upc, -5) == "00000") { $scaleprice = $this->scaleprice; $deliflag = true; } } } $db = Database::tDataConnect(); $query = "SELECT SUM(ItemQtty) AS voidable, \n SUM(quantity) AS vquantity,\n MAX(scale) AS scale,\n MAX(volDiscType) AS volDiscType \n FROM localtemptrans \n WHERE upc = '" . $upc . "'"; if ($deliflag) { $query .= ' AND unitPrice = ' . $scaleprice; } $query .= ' GROUP BY upc'; $result = $db->query($query); $num_rows = $db->num_rows($result); if ($num_rows == 0) { $json['output'] = DisplayLib::boxMsg(_("Item not found: ") . $upc, '', false, DisplayLib::standardClearButton()); return $json; } $row = $db->fetch_array($result); if ($row["scale"] == 1 && $weight > 0) { $quantity = $weight - CoreLocal::get("tare"); CoreLocal::set("tare", 0); } $volDiscType = $row["volDiscType"]; $voidable = MiscLib::nullwrap($row["voidable"]); $VolSpecial = 0; $volume = 0; $scale = MiscLib::nullwrap($row["scale"]); if ($voidable == 0 && $quantity == 1) { $json['output'] = DisplayLib::boxMsg(_("Item already voided"), '', false, DisplayLib::standardClearButton()); return $json; } elseif ($voidable == 0 && $quantity > 1) { $json['output'] = DisplayLib::boxMsg(_("Items already voided"), '', false, DisplayLib::standardClearButton()); return $json; } elseif ($scale == 1 && $quantity < 0) { $json['output'] = DisplayLib::boxMsg(_("tare weight cannot be greater than item weight"), '', false, DisplayLib::standardClearButton()); return $json; } elseif ($voidable < $quantity && $row["scale"] == 1) { $message = _("Void request exceeds") . "<br />" . _("weight of item rung in") . "<p><b>" . sprintf(_("You can void up to %.2f lb"), $row['voidable']) . "</b>"; $json['output'] = DisplayLib::boxMsg($message, '', false, DisplayLib::standardClearButton()); return $json; } elseif ($voidable < $quantity) { $message = _("Void request exceeds") . "<br />" . _("number of items rung in") . "<p><b>" . sprintf(_("You can void up to %d"), $row['voidable']) . "</b>"; $json['output'] = DisplayLib::boxMsg($message, '', false, DisplayLib::standardClearButton()); return $json; } //----------------------Void Item------------------ $query_upc = "SELECT \n ItemQtty,\n foodstamp,\n discounttype,\n mixMatch,\n cost,\n numflag,\n charflag,\n unitPrice,\n total,\n discounttype,\n regPrice,\n discount,\n memDiscount,\n discountable,\n description,\n trans_type,\n trans_subtype,\n department,\n tax,\n VolSpecial,\n matched,\n scale,\n trans_id\n FROM localtemptrans \n WHERE upc = '" . $upc . "'"; if ($deliflag) { $query_upc .= ' AND unitPrice = ' . $scaleprice; } if ($item_num != -1) { $query_upc .= ' AND trans_id = ' . $item_num; } else { $query_upc .= ' AND voided=0 ORDER BY total'; } $result = $db->query($query_upc); $row = $db->fetch_array($result); $foodstamp = MiscLib::nullwrap($row["foodstamp"]); $discounttype = MiscLib::nullwrap($row["discounttype"]); $mixMatch = MiscLib::nullwrap($row["mixMatch"]); $matched = -1 * $row['matched']; $item_num = $row['trans_id']; $cost = $row['cost']; $numflag = $row['numflag']; $charflag = $row['charflag']; $unitPrice = $row["unitPrice"]; /** 11Jun14 Andy Convert unitPrice to/from sale price based on member status. I'm not sure this is actually necessary. */ if (CoreLocal::get("isMember") != 1 && $row["discounttype"] == 2 || CoreLocal::get("isStaff") == 0 && $row["discounttype"] == 4) { $unitPrice = $row["regPrice"]; } elseif ((CoreLocal::get("isMember") == 1 && $row["discounttype"] == 2 || CoreLocal::get("isStaff") != 0 && $row["discounttype"] == 4) && $row["unitPrice"] == $row["regPrice"]) { $db_p = Database::pDataConnect(); $query_p = "select special_price from products where upc = '" . $upc . "'"; $result_p = $db_p->query($query_p); $row_p = $db_p->fetch_array($result_p); $unitPrice = $row_p["special_price"]; } $discount = -1 * $row["discount"]; $memDiscount = -1 * $row["memDiscount"]; $discountable = $row["discountable"]; $quantity = -1 * $quantity; $total = $quantity * $unitPrice; if ($row['unitPrice'] == 0) { $total = $quantity * $row['total']; } elseif ($row['total'] != $total && $row['scale'] == 1) { /** If the total does not match quantity times unit price, the cashier probably manually specified a quantity i.e., VD{qty}*{upc}. This is probably OK for non-weight items. Each record should be the same and voiding multiple in one line will usually be fine. */ $total = -1 * $row['total']; } /** Check if the voiding item will exceed the limit. If so, prompt for admin password. */ if (is_numeric(CoreLocal::get('VoidLimit')) && CoreLocal::get('VoidLimit') > 0) { $currentTotal = CoreLocal::get('voidTotal'); if ($currentTotal + -1 * $total > CoreLocal::get('VoidLimit') && CoreLocal::get('voidOverride') != 1) { CoreLocal::set('strRemembered', CoreLocal::get('strEntered')); CoreLocal::set('voidOverride', 0); $json['main_frame'] = MiscLib::base_url() . 'gui-modules/adminlogin.php?class=Void'; return $json; } } $db = Database::tDataConnect(); if (CoreLocal::get("tenderTotal") < 0 && -1 * $total > CoreLocal::get("runningTotal") - CoreLocal::get("taxTotal")) { $cash = $db->query("SELECT total FROM localtemptrans WHERE trans_subtype='CA' AND total <> 0"); if ($db->num_rows($cash) > 0) { $json['output'] = DisplayLib::boxMsg(_("Item already paid for"), '', false, DisplayLib::standardClearButton()); return $json; } } if ($quantity != 0) { $update = "update localtemptrans set voided = 1 where trans_id = " . $item_num; $db->query($update); TransRecord::addRecord(array('upc' => $upc, 'description' => $row["description"], 'trans_type' => $row["trans_type"], 'trans_subtype' => $row["trans_subtype"], 'trans_status' => "V", 'department' => $row["department"], 'quantity' => $quantity, 'unitPrice' => $unitPrice, 'total' => $total, 'regPrice' => $row["regPrice"], 'scale' => $scale, 'tax' => $row["tax"], 'foodstamp' => $foodstamp, 'discount' => $discount, 'memDiscount' => $memDiscount, 'discountable' => $discountable, 'discounttype' => $discounttype, 'ItemQtty' => $quantity, 'volDiscType' => $volDiscType, 'volume' => $volume, 'VolSpecial' => $VolSpecial, 'mixMatch' => $mixMatch, 'matched' => $matched, 'voided' => 1, 'cost' => $cost, 'numflag' => $numflag, 'charflag' => $charflag)); if ($row["trans_type"] != "T") { CoreLocal::set("ttlflag", 0); } $db = Database::pDataConnect(); $chk = $db->query("SELECT deposit FROM products WHERE upc='{$upc}'"); if ($db->num_rows($chk) > 0) { $w = $db->fetch_row($chk); $dpt = $w['deposit']; if ($dpt <= 0) { return $json; // no deposit found } $db = Database::tDataConnect(); $dupc = str_pad((int) $dpt, 13, '0', STR_PAD_LEFT); $id = $db->query(sprintf("SELECT trans_id FROM localtemptrans\n WHERE upc='%s' AND voided=0 AND quantity=%d", $dupc, -1 * $quantity)); if ($db->num_rows($id) > 0) { $w = $db->fetch_row($id); $trans_id = $w['trans_id']; // pass an empty array instead of $json so // voiding the deposit doesn't result in an error // message. $this->voidupc(-1 * $quantity . "*" . $dupc, array(), $trans_id); } } } return $json; }
public function handle($upc, $json) { /** Adjust string index of pieces based on whether check digits have been included */ $man_id_start = 3; $fam_start = 8; $val_start = 11; if ($this->ean && CoreLocal::get('EanIncludeCheckDigits') == 1 || !$this->ean && CoreLocal::get('UpcIncludeCheckDigits') == 1) { $man_id_start = 2; $fam_start = 9; $val_start = 10; } $man_id = substr($upc, $man_id_start, 5); $fam = substr($upc, $fam_start, 3); $val = substr($upc, $val_start, 2); $db = Database::pDataConnect(); $query = "select Value,Qty from couponcodes where Code = '" . $val . "'"; $result = $db->query($query); $num_rows = $db->num_rows($result); if ($num_rows == 0) { $json['output'] = DisplayLib::boxMsg(_("coupon type unknown") . "<br />" . _("enter coupon manually"), '', false, DisplayLib::standardClearButton()); return $json; } $query2 = "SELECT reason, threshold FROM disableCoupon WHERE upc='{$upc}'"; $result2 = $db->query($query2); if ($result2 && $db->num_rows($result2) > 0) { $row = $db->fetch_row($result2); if ($row['threshold'] <= 0) { $json['output'] = DisplayLib::boxMsg($row['reason'], _("coupon disabled"), false, DisplayLib::standardClearButton()); return $json; } else { $transDB = Database::tDataConnect(); $q = "SELECT SUM(quantity) FROM localtemptrans WHERE upc='{$upc}'"; $r = $transDB->query($q); if ($transDB->num_rows($r) > 0) { $w = $transDB->fetch_row($r); $qty = $w[0]; if ($qty >= $row['threshold']) { $json['output'] = DisplayLib::boxMsg(_('coupon already applied'), '', false, DisplayLib::standardClearButton()); return $json; } } } } $row = $db->fetch_array($result); $value = $row["Value"]; $qty = $row["Qty"]; if ($fam == "992") { // 992 basically means blanket accept // Old method of asking cashier to assign a department // just creates confusion // Instead I just try to guess, otherwise use zero // (since that's what would happen anyway when the // confused cashier does a generic coupon tender) $value = MiscLib::truncate2($value); CoreLocal::set("couponupc", $upc); CoreLocal::set("couponamt", $value); $dept = 0; $db = Database::tDataConnect(); // SQL strings are indexed starting w/ one instead of zero // hence $man_id_start+1 $query = "select department from localtemptrans \n WHERE substring(upc," . ($man_id_start + 1) . ",5)='{$man_id}' \n GROUP BY department\n ORDER BY count(*) desc"; $result = $db->query($query); if ($db->num_rows($result) > 0) { $row = $db->fetch_row($result); $dept = $row['department']; } TransRecord::addCoupon($upc, $dept, $value); $json['output'] = DisplayLib::lastpage(); return $json; } // validate coupon $db = Database::tDataConnect(); $fam = substr($fam, 0, 2); /* the idea here is to track exactly which items in the transaction a coupon was previously applied to SQL strings are indexed starting w/ one instead of zero hence $man_id_start+1 */ $query = "select max(t.unitPrice) as unitPrice,\n max(t.department) as department,\n max(t.ItemQtty) as itemQtty,\n sum(case when c.quantity is null then 0 else c.quantity end) as couponQtty,\n max(case when c.quantity is not null then 0 else t.foodstamp end) as foodstamp,\n max(case when c.quantity is not null then 0 else t.tax end) as tax,\n max(t.emp_no) as emp_no,\n max(t.trans_no) as trans_no,\n t.trans_id from\n localtemptrans as t left join couponApplied as c\n on t.emp_no=c.emp_no and t.trans_no=c.trans_no\n and t.trans_id=c.trans_id\n where (substring(t.upc," . ($man_id_start + 1) . ",5)='{$man_id}'"; /* not right per the standard, but organic valley doesn't * provide consistent manufacturer ids in the same goddamn * coupon book */ if ($this->ean) { $query .= " or substring(t.upc," . $man_id_start . ",5)='{$man_id}'"; } $query .= ") and t.trans_status <> 'C'\n group by t.trans_id\n order by t.unitPrice desc"; $result = $db->query($query); $num_rows = $db->num_rows($result); /* no item w/ matching manufacturer */ if ($num_rows == 0) { $json['output'] = DisplayLib::boxMsg(_("product not found") . "<br />" . _("in transaction"), '', false, DisplayLib::standardClearButton()); return $json; } /* count up per-item quantites that have not yet had a coupon applied to them */ $available = array(); $emp_no = $transno = $dept = $foodstamp = $tax = -1; $act_qty = 0; while ($row = $db->fetch_array($result)) { if ($row["itemQtty"] - $row["couponQtty"] > 0) { $id = $row["trans_id"]; $available["{$id}"] = array(0, 0); $available["{$id}"][0] = $row["unitPrice"]; $available["{$id}"][1] += $row["itemQtty"]; $available["{$id}"][1] -= $row["couponQtty"]; $act_qty += $available["{$id}"][1]; } if ($emp_no == -1) { $emp_no = $row["emp_no"]; $transno = $row["trans_no"]; $dept = $row["department"]; $foodstamp = $row["foodstamp"]; $tax = $row['tax']; } } /* every line has maximum coupons applied */ if (count($available) == 0) { $json['output'] = DisplayLib::boxMsg(_("Coupon already applied") . "<br />" . _("for this item"), '', false, DisplayLib::standardClearButton()); return $json; } /* insufficient number of matching items */ if ($qty > $act_qty) { $msg = sprintf(_("coupon requires %d items"), $qty) . "<br />" . sprintf(_("there are only %d item(s)"), $act_qty) . "<br />" . _("in this transaction"); $json['output'] = DisplayLib::boxMsg($msg, '', false, DisplayLib::standardClearButton()); return $json; } /* free item, multiple choices needs work, obviously */ if ($value == 0 && count($available) > 1) { // decide which item(s) // manually by cashier maybe? } /* log the item(s) this coupon is being applied to */ $applied = 0; foreach (array_keys($available) as $id) { if ($value == 0) { $value = -1 * $available["{$id}"][0]; } if ($qty <= $available["{$id}"][1]) { $q = "INSERT INTO couponApplied \n (emp_no,trans_no,quantity,trans_id)\n VALUES (\n {$emp_no},{$transno},{$qty},{$id})"; $r = $db->query($q); $applied += $qty; } else { $q = "INSERT INTO couponApplied \n (emp_no,trans_no,quantity,trans_id)\n VALUES (\n {$emp_no},{$transno}," . $available["{$id}"][1] . ",{$id})"; $r = $db->query($q); $applied += $available["{$id}"][1]; } if ($applied >= $qty) { break; } } $value = MiscLib::truncate2($value); $json['udpmsg'] = 'goodBeep'; TransRecord::addCoupon($upc, $dept, $value, $foodstamp, $tax); $json['output'] = DisplayLib::lastpage(); $json['redraw_footer'] = True; return $json; }
public function errorCheck() { return DisplayLib::xboxMsg($this->name_string . " " . _("tender disabled"), DisplayLib::standardClearButton()); }