Пример #1
0
 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;
 }
Пример #2
0
 /**
   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;
 }
Пример #3
0
 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;
 }
Пример #4
0
 /**
   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;
 }
Пример #5
0
 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;
 }
Пример #6
0
 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);
     }
 }
Пример #7
0
 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;
 }
Пример #8
0
 /**
   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;
 }
Пример #9
0
 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;
 }
Пример #10
0
 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;
 }
Пример #11
0
 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;
 }
Пример #12
0
 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("");
     }
 }
Пример #13
0
 /**
   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;
 }
Пример #14
0
 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;
 }
Пример #15
0
 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;
 }
Пример #16
0
 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;
 }
Пример #17
0
 /**
   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;
 }
Пример #18
0
 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;
 }
Пример #19
0
 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;
 }
Пример #20
0
 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;
 }
Пример #21
0
 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;
     }
 }
Пример #22
0
 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;
     }
 }
Пример #23
0
 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;
 }
Пример #24
0
 /**
   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;
 }
Пример #25
0
 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);
 }
Пример #26
0
 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 "";
 }
Пример #27
0
 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;
 }
Пример #28
0
 /**
   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;
 }
Пример #29
0
 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;
 }
Пример #30
0
 public function errorCheck()
 {
     return DisplayLib::xboxMsg($this->name_string . " " . _("tender disabled"), DisplayLib::standardClearButton());
 }