pos/is4c-nf/lib/Scanning/PriceMethods/QttyEnforcedGroupPM.php
<?php
/*******************************************************************************
Copyright 2010 Whole Foods Co-op
This file is part of IT CORE.
IT CORE is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
IT CORE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
in the file license.txt along with IT CORE; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*********************************************************************************/
namespace COREPOS\pos\lib\Scanning\PriceMethods;
use COREPOS\pos\lib\Scanning\PriceMethod;
use COREPOS\pos\lib\Database;
use COREPOS\pos\lib\MiscLib;
use COREPOS\pos\lib\TransRecord;
/**
@class QttyEnforcedGroupPM
This module provides grouped sales where the
customer is required to buy a "complete set"
before the group discount is applied
In most locations, this is pricemethod 1 or 2
*/
class QttyEnforcedGroupPM extends PriceMethod {
public function addItem(array $row, $quantity, $priceObj)
{
if ($quantity == 0) return false;
$pricing = $priceObj->priceInfo($row,$quantity);
// enforce limit on discounting sale items
$dsi = $this->session->get('DiscountableSaleItems');
if ($dsi == 0 && $dsi !== '' && $priceObj->isSale()) {
$row['discount'] = 0;
}
/* group definition: number of items
that make up a group, price for a
full set. Use "special" rows if the
item is on sale */
$groupQty = $row['quantity'];
$groupPrice = $row['groupprice'];
if ($priceObj->isSale()){
$groupQty = $row['specialquantity'];
$groupPrice = $row['specialgroupprice'];
}
/* calculate how many complete sets are
present in this scan and how many remain
after complete sets */
$newSets = floor($quantity / $groupQty);
$remainder = $quantity % $groupQty;
/* add complete sets */
if ($newSets > 0){
$percentDiscount = 0;
if (!$priceObj->isSale() && $pricing['unitPrice'] != $row['normal_price']){
$percentDiscount = ($row['normal_price'] - $pricing['unitPrice']) / $row['normal_price'];
$groupPrice *= (1 - $percentDiscount);
}
else if ($priceObj->isSale() && $pricing['unitPrice'] != $row['special_price']){
$percentDiscount = ($row['special_price'] - $pricing['unitPrice']) / $row['special_price'];
$groupPrice *= (1 - $percentDiscount);
}
/* discount for complete set */
$discount = $newSets * (($pricing['unitPrice']*$groupQty) - $groupPrice);
$total = ($newSets* $groupQty * $pricing['unitPrice']) - $discount;
$unit = $total / ($newSets * $groupQty);
$memDiscount = 0;
if ($priceObj->isMemberSale() || $priceObj->isStaffSale()){
$memDiscount = $discount;
$discount = 0;
}
TransRecord::addRecord(array(
'upc' => $row['upc'],
'description' => $row['description'],
'trans_type' => 'I',
'trans_subtype' => (isset($row['trans_subtype'])) ? $row['trans_subtype'] : '',
'department' => $row['department'],
'quantity' => $newSets * $groupQty,
'unitPrice' => MiscLib::truncate2($unit),
'total' => MiscLib::truncate2($total),
'regPrice' => $pricing['regPrice'],
'scale' => $row['scale'],
'tax' => $row['tax'],
'foodstamp' => $row['foodstamp'],
'discount' => $discount,
'memDiscount' => $memDiscount,
'discountable' => $row['discount'],
'discounttype' => $row['discounttype'],
'ItemQtty' => $newSets * $groupQty,
'volDiscType' => ($priceObj->isSale() ? $row['specialpricemethod'] : $row['pricemethod']),
'volume' => ($priceObj->isSale() ? $row['specialquantity'] : $row['quantity']),
'VolSpecial' => ($priceObj->isSale() ? $row['specialgroupprice'] : $row['groupprice']),
'mixMatch' => $row['mixmatchcode'],
'matched' => $newSets * $groupQty,
'cost' => (isset($row['cost']) ? $row['cost']*$newSets*$groupQty : 0.00),
'numflag' => (isset($row['numflag']) ? $row['numflag'] : 0),
'charflag' => (isset($row['charflag']) ? $row['charflag'] : '')
));
if ($percentDiscount != 0){
$discount -= $pricing['discount'];
}
TransRecord::adddiscount($discount,$row['department']);
$quantity = $quantity - ($newSets * $groupQty);
if ($quantity < 0) $quantity = 0;
}
/* if potential matches remain, check for sets */
if ($remainder > 0){
/* count items in the transaction
from the given group, minus
items that have already been used
in a grouping */
$mixMatch = $row["mixmatchcode"];
$queryt = "select sum(ItemQtty - matched) as mmqtty,
mixMatch from localtemptrans
where trans_status <> 'R' AND
mixMatch = '".$mixMatch."' group by mixMatch";
$mixedSet = true;
if (!$mixMatch || $mixMatch == '0') {
$mixMatch = 0;
$queryt = "select sum(ItemQtty - matched) as mmqtty from "
."localtemptrans where trans_status<>'R' AND "
."upc = '".$row['upc']."' group by upc";
$mixedSet = false;
}
$dbt = Database::tDataConnect();
$resultt = $dbt->query($queryt);
$numRowst = $dbt->num_rows($resultt);
$transQty = 0;
if ($numRowst > 0){
$rowt = $dbt->fetchRow($resultt);
$transQty = floor($rowt['mmqtty']);
}
/* remainder from current scan plus existing
unmatched items complete a new set, so
add one item with the group discount */
if ($transQty + $remainder >= $groupQty){
/* adjusted price for the "last" item in a set */
$priceAdjust = $groupPrice - (($groupQty-1) * $pricing['unitPrice']);
$discount = $pricing['unitPrice'] - $priceAdjust;
/**
* Is a BOGO deal covering multiple items
* Lookup the price of the last un-matched item which will
* form this BOGO pairing. If the previous item is
* cheaper, use it's price for the discount value to
* make it functionally the free item
*/
if ($mixedSet && $groupQty == 2 && abs($pricing['unitPrice'] - $discount) <= 0.005) {
$queryPrice = "select unitPrice
from localtemptrans
where trans_status <> 'R' AND
mixMatch = '".$mixMatch."'
ORDER BY matched, datetime DESC";
$priceR = $dbt->query($queryPrice);
$priceW = $dbt->fetchRow($priceR);
if ($priceW && $priceW['unitPrice'] < $pricing['unitPrice']) {
$discount = $priceW['unitPrice'];
}
}
$memDiscount = 0;
if ($priceObj->isMemberSale() || $priceObj->isStaffSale()){
$memDiscount = $discount;
$discount = 0;
}
TransRecord::addRecord(array(
'upc' => $row['upc'],
'description' => $row['description'],
'trans_type' => 'I',
'trans_subtype' => (isset($row['trans_subtype'])) ? $row['trans_subtype'] : '',
'department' => $row['department'],
'quantity' => 1,
'unitPrice' => $pricing['unitPrice'] - $discount,
'total' => $pricing['unitPrice'] - $discount,
'regPrice' => $pricing['regPrice'],
'scale' => $row['scale'],
'tax' => $row['tax'],
'foodstamp' => $row['foodstamp'],
'discount' => $discount,
'memDiscount' => $memDiscount,
'discountable' => $row['discount'],
'discounttype' => $row['discounttype'],
'ItemQtty' => 1,
'volDiscType' => ($priceObj->isSale() ? $row['specialpricemethod'] : $row['pricemethod']),
'volume' => ($priceObj->isSale() ? $row['specialquantity'] : $row['quantity']),
'VolSpecial' => ($priceObj->isSale() ? $row['specialgroupprice'] : $row['groupprice']),
'mixMatch' => $row['mixmatchcode'],
'matched' => $groupQty,
'cost' => (isset($row['cost']) ? $row['cost']*$newSets*$groupQty : 0.00),
'numflag' => (isset($row['numflag']) ? $row['numflag'] : 0),
'charflag' => (isset($row['charflag']) ? $row['charflag'] : '')
));
$quantity -= 1;
if ($quantity < 0) $quantity = 0;
}
}
/* any remaining quantity added without
grouping discount */
if ($quantity > 0){
TransRecord::addRecord(array(
'upc' => $row['upc'],
'description' => $row['description'],
'trans_type' => 'I',
'trans_subtype' => (isset($row['trans_subtype'])) ? $row['trans_subtype'] : '',
'department' => $row['department'],
'quantity' => $quantity,
'unitPrice' => $pricing['unitPrice'],
'total' => MiscLib::truncate2($pricing['unitPrice'] * $quantity),
'regPrice' => $pricing['regPrice'],
'scale' => $row['scale'],
'tax' => $row['tax'],
'foodstamp' => $row['foodstamp'],
'discountable' => $row['discount'],
'discounttype' => $row['discounttype'],
'ItemQtty' => $quantity,
'volDiscType' => ($priceObj->isSale() ? $row['specialpricemethod'] : $row['pricemethod']),
'volume' => ($priceObj->isSale() ? $row['specialquantity'] : $row['quantity']),
'VolSpecial' => ($priceObj->isSale() ? $row['specialgroupprice'] : $row['groupprice']),
'mixMatch' => $row['mixmatchcode'],
'cost' => (isset($row['cost'])?$row['cost']*$quantity:0.00),
'numflag' => (isset($row['numflag'])?$row['numflag']:0),
'charflag' => (isset($row['charflag'])?$row['charflag']:'')
));
}
return True;
}
}