Example #1
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;
 }
Example #2
0
 /**
   Add an open ring to a department
   @param $price amount in cents (100 = $1)
   @param $dept POS department
   @ret an array of return values
   @returns An array. See Parser::default_json()
    for format explanation.
 */
 public static function deptkey($price, $dept, $ret = array())
 {
     if (CoreLocal::get("quantity") == 0 && CoreLocal::get("multiple") == 0) {
         CoreLocal::set("quantity", 1);
     }
     $ringAsCoupon = false;
     if (substr($price, 0, 2) == 'MC') {
         $ringAsCoupon = true;
         $price = substr($price, 2);
     }
     if (!is_numeric($dept) || !is_numeric($price) || strlen($price) < 1 || strlen($dept) < 2) {
         $ret['output'] = DisplayLib::inputUnknown();
         CoreLocal::set("quantity", 1);
         $ret['udpmsg'] = 'errorBeep';
         return $ret;
     }
     $strprice = $price;
     $strdept = $dept;
     $price = $price / 100;
     $dept = $dept / 10;
     $discount = 0;
     if (CoreLocal::get("casediscount") > 0 && CoreLocal::get("casediscount") <= 100) {
         $case_discount = (100 - CoreLocal::get("casediscount")) / 100;
         $price = $case_discount * $price;
     } elseif (CoreLocal::get('itemPD') > 0 && CoreLocal::get('SecurityLineItemDiscount') == 30 && CoreLocal::get('msgrepeat') == 0) {
         $ret['main_frame'] = MiscLib::baseURL() . "gui-modules/adminlogin.php?class=LineItemDiscountAdminLogin";
         return $ret;
     } elseif (CoreLocal::get('itemPD') > 0) {
         $discount = MiscLib::truncate2($price * (CoreLocal::get('itemPD') / 100.0));
         $price -= $discount;
     }
     $discount = $discount * CoreLocal::get('quantity');
     $query = "SELECT dept_no,\n        dept_name,\n        dept_tax,\n        dept_fs,\n        dept_limit,\n        dept_minimum,\n        dept_discount,";
     $dbc = Database::pDataConnect();
     $table = $dbc->table_definition('departments');
     if (isset($table['dept_see_id'])) {
         $query .= 'dept_see_id,';
     } else {
         $query .= '0 as dept_see_id,';
     }
     if (isset($table['memberOnly'])) {
         $query .= 'memberOnly';
     } else {
         $query .= '0 AS memberOnly';
     }
     $query .= " FROM departments \n                WHERE dept_no = " . (int) $dept;
     $result = $dbc->query($query);
     $num_rows = $dbc->num_rows($result);
     if ($num_rows == 0) {
         $ret['output'] = DisplayLib::boxMsg(_("department unknown"), '', false, DisplayLib::standardClearButton());
         $ret['udpmsg'] = 'errorBeep';
         CoreLocal::set("quantity", 1);
     } elseif ($ringAsCoupon) {
         $row = $dbc->fetch_array($result);
         $ret = self::deptCouponRing($row, $price, $ret);
     } else {
         $row = $dbc->fetch_array($result);
         $my_url = MiscLib::baseURL();
         if ($row['dept_see_id'] > 0) {
             list($bad_age, $ret) = PrehLib::ageCheck($row['dept_see_id'], $ret);
             if ($bad_age === true) {
                 return $ret;
             }
         }
         $ret = self::deptOpenRing($row, $price, $discount, $ret);
     }
     CoreLocal::set("quantity", 0);
     CoreLocal::set("itemPD", 0);
     return $ret;
 }
Example #3
0
 public function testPrehLib()
 {
     if (!class_exists('lttLib')) {
         include 'lttLib.php';
     }
     lttLib::clear();
     TransRecord::addcomment('peek');
     $peek = PrehLib::peekItem();
     $this->assertEquals('peek', $peek);
     lttLib::clear();
     CoreLocal::set('percentDiscount', 5);
     CoreLocal::set('transDiscount', 0.51);
     CoreLocal::set('taxTotal', 1.45);
     CoreLocal::set('fsTaxExempt', 1.11);
     CoreLocal::set('amtdue', 9.550000000000001);
     // should add four records
     PrehLib::finalttl();
     // verify discount record
     $record = lttLib::genericRecord();
     $record['description'] = 'Discount';
     $record['trans_type'] = 'C';
     $record['trans_status'] = 'D';
     $record['unitPrice'] = -0.51;
     $record['voided'] = 5;
     lttLib::verifyRecord(1, $record, $this);
     // verify subtotal record
     $record = lttLib::genericRecord();
     $record['upc'] = 'Subtotal';
     $record['description'] = 'Subtotal';
     $record['trans_type'] = 'C';
     $record['trans_status'] = 'D';
     $record['unitPrice'] = 0.34;
     $record['voided'] = 11;
     lttLib::verifyRecord(2, $record, $this);
     // verify fs tax exempt record
     $record = lttLib::genericRecord();
     $record['upc'] = 'Tax';
     $record['description'] = 'FS Taxable';
     $record['trans_type'] = 'C';
     $record['trans_status'] = 'D';
     $record['unitPrice'] = 1.11;
     $record['voided'] = 7;
     lttLib::verifyRecord(3, $record, $this);
     // verify total record
     $record = lttLib::genericRecord();
     $record['upc'] = 'Total';
     $record['description'] = 'Total';
     $record['trans_type'] = 'C';
     $record['trans_status'] = 'D';
     $record['unitPrice'] = 9.550000000000001;
     $record['voided'] = 11;
     lttLib::verifyRecord(4, $record, $this);
     lttLib::clear();
     CoreLocal::set('cashierAge', 17);
     CoreLocal::set('cashierAgeOverride', 0);
     list($age_required, $json) = PrehLib::ageCheck(21, array());
     $this->assertEquals(true, $age_required);
     $this->assertInternalType('array', $json);
     CoreLocal::set('cashierAgeOverride', 1);
     list($age_required, $json) = PrehLib::ageCheck(21, array());
     $this->assertEquals(true, $age_required);
     $this->assertInternalType('array', $json);
     CoreLocal::set('memAge', date('Ymd', strtotime('21 years ago')));
     list($age_required, $json) = PrehLib::ageCheck(21, array());
     $this->assertEquals(false, $age_required);
     $this->assertInternalType('array', $json);
     CoreLocal::set('memAge', date('Ymd', strtotime('20 years ago')));
     list($age_required, $json) = PrehLib::ageCheck(21, array());
     $this->assertEquals(true, $age_required);
     $this->assertInternalType('array', $json);
 }