fannie/modules/plugins2.0/RP/RpDirectPage.php
<?php
include(__DIR__ . '/../../../config.php');
if (!class_exists('FannieAPI')) {
include(__DIR__ . '/../../../classlib2.0/FannieAPI.php');
}
if (!class_exists('RpOrderCategoriesModel')) {
include(__DIR__ . '/models/RpOrderCategoriesModel.php');
}
if (!class_exists('RpOrderItemsModel')) {
include(__DIR__ . '/models/RpOrderItemsModel.php');
}
if (!class_exists('RpSessionsModel')) {
include(__DIR__ . '/models/RpSessionsModel.php');
}
if (!class_exists('RpSnapshotsModel')) {
include(__DIR__ . '/models/RpSnapshotsModel.php');
}
if (!class_exists('RpFarmsModel')) {
include(__DIR__ . '/models/RpFarmsModel.php');
}
class RpDirectPage extends FannieRESTfulPage
{
protected $header = 'Daily Direct Guide';
protected $title = 'Daily Direct Guide';
protected $must_authenticate = true;
public function preprocess()
{
$this->addRoute('get<searchVendor>', 'get<searchLC>', 'get<json>', 'get<date1><date2>', 'get<clear>', 'post<json>');
$this->userID = FannieAuth::getUID($this->current_user);
return parent::preprocess();
}
protected function get_date1_date2_handler()
{
$date1 = date('Y-m-d', strtotime(FormLib::get('date1')));
$date2 = date('Y-m-d', strtotime(FormLib::get('date2')));
$args = array(FormLib::get('store'), $date1, $date2);
$ignore = 'CASE WHEN receivedDate < ' . $this->connection->curdate() . ' THEN 1 ELSE 0 END AS ignored';
/**
* Check for past dates. Since the purpose it to view future expected
* deliveries, selected weekdays that are in the past should be pushed
* forward into the subsequent week
*/
$ts1 = strtotime($date1);
$ts2 = strtotime($date2);
$today = strtotime(date('Y-m-d'));
if ($ts1 < $today) {
$ts1 = mktime(0, 0, 0, date('n', $ts1), date('j', $ts1) + 7, date('Y', $ts1));
}
if ($ts2 < $today) {
$ts2 = mktime(0, 0, 0, date('n', $ts2), date('j', $ts2) + 7, date('Y', $ts2));
}
if ($ts1 > $ts2) {
$swap = $ts2;
$ts2 = $ts1;
$ts1 = $swap;
}
$date1 = date('Y-m-d', $ts1);
$date2 = date('Y-m-d', $ts2);
$date3 = false;
$extra = FormLib::get('date3');
$d3ts = strtotime($extra);
if ($d3ts && $extra) {
$date3 = date('Y-m-d', $d3ts);
// safe embed because it's a formatted date string or false
// for any user input
$ignore = "CASE WHEN receivedDate > {$date2} OR receivedDate < " . $this->connection->curdate() . "
THEN 1 ELSE 0 END AS ignored";
$args[2] = $date3;
}
$prep = $this->connection->prepare("SELECT receivedDate, internalUPC AS upc, brand, quantity AS qty, caseSize,
{$ignore}
FROM PurchaseOrderItems AS i
INNER JOIN PurchaseOrder AS o ON i.orderID=o.orderID
WHERE (o.vendorID=-2 OR o.vendorInvoiceID LIKE 'PREBOOK %')
AND o.userID=-99
AND o.placed=1
AND o.storeID=?
AND i.receivedDate IS NOT NULL
AND (
i.receivedDate BETWEEN ? AND ?
OR i.receivedDate = " . $this->connection->curdate() . "
)
ORDER BY i.receivedDate
");
$qtys = $this->connection->getAllRows($prep, $args);
$ret = array();
foreach ($qtys as $row) {
if (!isset($ret[$row['upc']])) {
$ret[$row['upc']] = array('upc' => $row['upc'], 'qty' => 0, 'text' => '');
}
if ($row['caseSize'] > 1) {
$row['qty'] *= $row['caseSize'];
}
if ($row['ignored'] != 1) {
$ret[$row['upc']]['qty'] += $row['qty'];
}
if ($ret[$row['upc']]['text'] != '') {
$ret[$row['upc']]['text'] .= '<br />';
}
$ts = strtotime($row['receivedDate']);
$text = date('n/j', $ts) . ' ' . $row['qty'] . ' ' . $row['brand'];
$ret[$row['upc']]['text'] .= $text;
}
$dekey = array();
foreach ($ret as $upc => $row) {
$dekey[] = $row;
}
echo json_encode($dekey);
return false;
}
protected function get_clear_handler()
{
$_SESSION['rpState'] = 'false';
$model = new RpSessionsModel($this->connection);
$model->dataType('RP');
$model->userID($this->userID);
$snap = new RpSnapshotsModel($this->connection);
$snap->userID($model->userID());
$snap->tdate(date('Y-m-d H:i:s'));
$snap->data($model->data());
$snap->dataType($model->dataType());
$snap->save();
$model->delete();
return 'RpDirectPage.php';
}
protected function post_json_handler()
{
return $this->get_json_handler();
}
protected function get_json_handler()
{
$_SESSION['rpState'] = json_decode($this->json, true);
$model = new RpSessionsModel($this->connection);
$model->userID($this->userID);
$model->dataType('RP');
$model->data($this->json);
$model->save();
echo 'OK';
return false;
}
protected function get_searchLC_handler()
{
$prep = $this->connection->prepare("SELECT * FROM likeCodes WHERE likeCodeDesc LIKE ?");
$res = $this->connection->getAllRows($prep, array('%' . $this->searchLC . '%'));
$ret = array();
foreach ($res as $row) {
$ret[] = array(
'label' => $row['likeCodeDesc'],
'value' => $row['likeCode'],
);
}
echo json_encode($ret);
return false;
}
protected function get_searchVendor_handler()
{
$query = "SELECT * FROM vendorItems WHERE (description LIKE ? OR brand LIKE ?)";
$args = array('%' . $this->searchVendor . '%', '%' . $this->searchVendor . '%');
if (FormLib::get('vendorID')) {
$args[] = FormLib::get('vendorID');
$query .= ' AND vendorID=?';
} else {
$query .= ' AND vendorID IN (292, 293, 136)';
}
$ret = array();
$prep = $this->connection->prepare($query);
$res = $this->connection->execute($prep, $args);
while ($row = $this->connection->fetchRow($res)) {
$label = $row['description'] . ' ' . $row['units'] . '/' . $row['size'] . ' ($' . $row['cost'] . ')';
$value = array(
'vendorID' => $row['vendorID'],
'caseSize' => $row['units'],
'sku' => $row['sku'],
'upc' => $row['upc'],
'item' => $row['description'],
);
$value = json_encode($value);
$ret[] = array(
'label' => $label,
'value' => $value,
);
}
echo json_encode($ret);
return false;
}
protected function delete_id_handler()
{
// forcing sequential requests here
$_SESSION['appendingOrder'] = true;
list($upc, $store, $vendor) = explode(',', $this->id);
$vendor = -2;
$findP = $this->connection->prepare("SELECT orderID
FROM PurchaseOrder WHERE placed=0 AND storeID=? AND vendorID=? AND userID=-99");
$orderID = $this->connection->getValue($findP, array($store, $vendor));
$delQ = "DELETE FROM PurchaseOrderItems
WHERE orderID=? AND internalUPC=?";
$args = array($orderID, $upc);
$farm = FormLib::get('farm', false);
if ($farm) {
$delQ .= ' AND brand=?';
$args[] = $farm;
}
$delP= $this->connection->prepare($delQ);
$this->connection->execute($delP, $args);
echo json_encode(array('unlink' => false));
return false;
}
protected function post_id_handler()
{
// forcing sequential requests here
$_SESSION['appendingOrder'] = true;
list($upc, $store, $vendor) = explode(',', $this->id);
$vendor = -2;
$findP = $this->connection->prepare("SELECT orderID
FROM PurchaseOrder WHERE placed=0 AND storeID=? AND vendorID=? AND userID=-99");
$orderID = $this->connection->getValue($findP, array($store, $vendor));
if (!$orderID) {
$model = new PurchaseOrderModel($this->connection);
$model->storeID($store);
$model->vendorID($vendor);
$model->creationDate(date('Y-m-d H:i:s'));
$model->userID(-99);
$orderID = $model->save();
}
$itemP = $this->connection->prepare("SELECT * FROM RpOrderItems WHERE upc=? AND storeID=?");
$item = $this->connection->getRow($itemP, array($upc, $store));
if ($item === false) {
$itemP = $this->connection->prepare("SELECT * FROM RpLocalItems WHERE upc=?");
$item = $this->connection->getRow($itemP, array($upc));
}
if (substr($upc, 0, 2) == "LC") {
$prodP = $this->connection->prepare("SELECT p.brand, p.size, p.cost FROM upcLike AS u
INNER JOIN products AS p ON u.upc=p.upc WHERE u.likeCode=?");
$prod = $this->connection->getRow($prodP, array(substr($upc, 2)));
} else {
$prodP = $this->connection->prepare("SELECT brand, size, cost FROM products WHERE upc=?");
$prod = $this->connection->getRow($prodP, array($upc));
}
// use RP cost
$prod['cost'] = $item['cost'] / $item['caseSize'];
$mapP = $this->connection->prepare("SELECT sku FROM RpFixedMaps WHERE likeCode=?");
$mapped = $this->connection->getValue($mapP, array(str_replace('LC', '', $upc)));
if ($mapped) {
$item['vendorSKU'] = $mapped;
}
if (!$item['vendorSKU']) {
$item['vendorSKU'] = $upc;
}
if (!$item['backupSKU']) {
$item['backupSKU'] = $upc;
}
$sku = $vendor == $item['backupID'] ? $item['backupSKU'] : $item['vendorSKU'];
if ($sku == 'DIRECT') {
$sku = $upc;
}
$farm = FormLib::get('farm');
if ($farm) {
$words = array_map('trim', explode(' ', $farm));
$words = array_filter($words, function ($i) { return strlen($i) > 0; });
$initials = array_reduce($words, function($c, $i) { return $c . $i[0]; });
$sku = $initials . $sku;
$poi = new PurchaseOrderItemsModel($this->connection);
$poi->orderID($orderID);
$poi->sku($sku);
$poi->quantity(FormLib::get('qty'));
$poi->unitCost($prod['cost']);
$poi->caseSize(1);
$poi->unitSize(isset($prod['size']) ? $prod['size'] : '');
$poi->brand($farm);
$poi->description($vendor == $item['backupID'] ? $item['backupItem'] : $item['vendorItem']);
$poi->internalUPC($upc);
$poi->save();
}
$vendP = $this->connection->prepare("SELECT vendorName FROM vendors WHERE vendorID=?");
$vend = $this->connection->getValue($vendP, array($vendor));
echo json_encode(array('orderID' => $orderID, 'name'=>$vend));
$_SESSION['appendingOrder'] = false;
return false;
}
protected function post_view()
{
$model = new RpOrderItemsModel($this->connection);
$model->storeID(FormLib::get('store'));
$model->categoryID(FormLib::get('catID'));
$model->addedBy(1);
$model->caseSize(FormLib::get('caseSize'));
$model->vendorID(FormLib::get('vendor'));
$model->vendorSKU(FormLib::get('sku'));
$model->vendorItem(FormLib::get('item'));
$lc = FormLib::get('lc');
$upc = BarcodeLib::padUPC(FormLib::get('upc'));
if ($lc) {
$model->upc('LC' . $lc);
} elseif ($upc != '0000000000000') {
$model->upc($upc);
} elseif (FormLib::get('sku')) {
$model->upc(FormLib::get('sku'));
} else {
$model->upc(uniqid());
}
$saved = $model->save();
$ret = '';
if ($saved) {
$ret .= '<div class="alert alert-success">Added item</div>';
} else {
$ret .= '<div class="alert alert-danger">Error adding item</div>';
}
return $ret . $this->get_view();
}
protected function isMobile()
{
$userAgent = strtolower(filter_input(INPUT_SERVER, 'HTTP_USER_AGENT'));
if (strstr($userAgent, 'android')) {
return true;
} elseif (strstr($userAgent, 'iphone os')) {
return true;
}
return false;
}
protected function get_view()
{
$this->addScript('rpDirect.js?date=20200708');
$this->addOnloadCommand('rpOrder.initAutoCompletes();');
$store = FormLib::get('store');
if (!$store) {
$store = COREPOS\Fannie\API\lib\Store::getIdByIp();
}
$sSelect = FormLib::storePicker();
$sSelect['html'] = str_replace('<select', '<select onchange="location=\'RpDirectPage.php?store=\' + this.value;"', $sSelect['html']);
$jsState = isset($_SESSION['rpState']) ? json_encode($_SESSION['rpState']) : "false";
if ($jsState === "false") {
$sModel = new RpSessionsModel($this->connection);
$sModel->dataType('RP');
$sModel->userID($this->userID);
if ($sModel->load()) {
$jsState = $sModel->data();
$_SESSION['rpState'] = json_decode($sModel->data(), true);
}
}
$this->addOnloadCommand("rpOrder.initState({$jsState});");
$fieldType = $this->isMobile() ? 'type="number" min="0" max="99999" step="0.01"' : 'type="text"';
$ordersP = $this->connection->prepare("
SELECT o.orderID, v.vendorName
FROM PurchaseOrder AS o
LEFT JOIN vendors AS v ON o.vendorID=v.vendorID
WHERE o.storeID=?
AND o.placed=0
AND o.userID=-99");
$orderLinks = '';
$orderIDs = array();
$orders = $this->connection->getAllRows($ordersP, array($store));
foreach ($orders as $o) {
$orderIDs[] = $o['orderID'];
$orderLinks .= sprintf('<li id="link%d"><a href="../../../purchasing/ViewPurchaseOrders.php?id=%d">%s</a></li>',
$o['orderID'], $o['orderID'], $o['vendorName']);
}
$printLink = '';
if (count($orderIDs) > 0) {
$printLink = '<a href="RpPrintOrders.php?id=' . implode(',', $orderIDs) . '">Print these</a>';
}
list($ioStr, $ioArgs) = $this->connection->safeInClause($orderIDs);
$inOrderP = $this->connection->prepare("SELECT vendorID, quantity FROM PurchaseOrder AS o
INNER JOIN PurchaseOrderItems AS i ON o.orderID=i.orderID
WHERE o.orderID IN ({$ioStr}) AND i.internalUPC=?");
$parP = $this->connection->prepare("
SELECT movement
FROM " . FannieDB::fqn('Smoothed', 'plugin:WarehouseDatabase') . "
WHERE storeID=?
AND upc=?");
$priceP = $this->connection->prepare("
SELECT CASE WHEN p.special_price > 0 THEN p.special_price ELSE p.normal_price END AS price
FROM upcLike AS u
INNER JOIN products AS p ON p.upc=u.upc
WHERE u.likeCode=?");
$costP = $this->connection->prepare("SELECT cost, units FROM vendorItems WHERE vendorID=? and sku=?");
$mapP = $this->connection->prepare("SELECT * FROM RpFixedMaps WHERE likeCode=?");
$lcP = $this->connection->prepare("SELECT likeCodeDesc, organic FROM likeCodes WHERE likeCode=?");
$dow = date('N');
$saleDate = date('Y-m-d');
if ($dow >= 6 || $dow <= 2) {
$ts = time();
while (date('N', $ts) != 3) {
$ts = mktime(0, 0, 0, date('n',$ts), date('j',$ts) + 1, date('Y',$ts));
}
$saleDate = date('Y-m-d', $ts);
}
$saleP = $this->connection->prepare("SELECT endDate
FROM batchList AS l
INNER JOIN batches AS b ON l.batchID=b.batchID
INNER JOIN StoreBatchMap AS m ON l.batchID=m.batchID
WHERE l.upc=? AND m.storeID=?
AND '{$saleDate}' BETWEEN startDate AND endDate
AND b.discountType > 0");
$ago = date('Y-m-d', strtotime('-3 days'));
$ahead = date('Y-m-d', strtotime('+3 days'));
$startingP = $this->connection->prepare("SELECT startDate
FROM batchList AS l
INNER JOIN batches AS b ON l.batchID=b.batchID
INNER JOIN StoreBatchMap AS m ON l.batchID=m.batchID
WHERE l.upc=? AND m.storeID=?
AND b.startDate BETWEEN '{$ago}' AND '{$ahead}'
AND b.discountType > 0");
$endingP = $this->connection->prepare("SELECT endDate
FROM batchList AS l
INNER JOIN batches AS b ON l.batchID=b.batchID
INNER JOIN StoreBatchMap AS m ON l.batchID=m.batchID
WHERE l.upc=? AND m.storeID=?
AND b.endDate BETWEEN '{$ago}' AND '{$ahead}'
AND b.discountType > 0");
$primaryP = $this->connection->prepare("SELECT rpFarmID FROM RpFarmSchedules
WHERE ? BETWEEN startDate AND endDate
AND likeCode=?
AND isPrimary=1");
$secondaryP = $this->connection->prepare("SELECT rpFarmID FROM RpFarmSchedules
WHERE ? BETWEEN startDate AND endDate
AND likeCode=?
AND isPrimary=0");
$directLCP = $this->connection->prepare("SELECT likeCode FROM RpLocalLCs");
$directLCs = $this->connection->getAllValues($directLCP);
$farmP = $this->connection->prepare("SELECT * FROM RpFarms");
$farms = $this->connection->getAllRows($farmP);
$prep = $this->connection->prepare("
SELECT r.upc,
r.categoryID,
c.name,
v.vendorName AS vendorName,
b.vendorName AS backupVendor,
r.vendorSKU,
r.vendorItem,
r.backupSKU,
r.backupItem,
r.caseSize,
r.vendorID,
r.backupID,
r.cost,
c.seq,
0 AS pri
FROM RpOrderItems AS r
LEFT JOIN RpOrderCategories AS c ON r.categoryID=c.rpOrderCategoryID
LEFT JOIN vendors AS v ON r.vendorID=v.vendorID
LEFT JOIN vendors AS b ON r.backupID=b.vendorID
WHERE r.storeID=?
AND r.deleted=0
UNION ALL
SELECT r.upc,
r.categoryID,
c.name,
v.vendorName AS vendorName,
b.vendorName AS backupVendor,
r.vendorSKU,
r.vendorItem,
r.backupSKU,
r.backupItem,
r.caseSize,
r.vendorID,
r.backupID,
r.cost,
c.seq,
1 AS pri
FROM RpLocalItems AS r
LEFT JOIN RpOrderCategories AS c ON r.categoryID=c.rpOrderCategoryID
LEFT JOIN vendors AS v ON r.vendorID=v.vendorID
LEFT JOIN vendors AS b ON r.backupID=b.vendorID
WHERE r.likeCode IN (SELECT likeCode FROM RpLocalLCs)
ORDER BY seq, pri, name, vendorItem
");
$res = $this->connection->execute($prep, array($store));
$tables = '';
$category = false;
$hiddenItems = '';
$seen = array();
while ($row = $this->connection->fetchRow($res)) {
if (isset($seen[$row['upc']])) {
continue;
}
$seen[$row['upc']] = true;
$likeCode = substr($row['upc'], 2);
$localLC = $likeCode;
if (strpos($localLC, '-')) {
list($localLC,) = explode('-', $localLC, 2);
}
$appendTables = true;
if (!in_array($localLC, $directLCs) && $row['vendorID'] != -2 && $row['backupID'] != -2) {
$appendTables = false;
}
if ($row['categoryID'] !== $category && $appendTables) {
if ($category !== false) {
$tables .= '</table>';
}
$catName = $row['categoryID'] ? $row['name'] : 'Uncategorized';
$tables .= '<h3>' . $catName . '</h3>';
$category = $row['categoryID'];
$tables .= '<table class="table table-bordered table-striped small">
<tr><th>LC</th><th>Primary</th><th>Secondary</th><th>Item</th>
<th>On Hand</th><th>Par</th><th colspan="2">Order</th></tr>';
}
$mapped = $this->connection->getRow($mapP, array(str_replace('LC', '', $row['upc'])));
if ($mapped) {
$row['vendorSKU'] = $mapped['sku'];
$row['lookupID'] = $mapped['vendorID'];
}
$organic = false;
$lcName = $row['vendorItem'];
if (is_numeric(str_replace('LC', '', $row['upc']))) {
$lcRow = $this->connection->getRow($lcP, array(str_replace('LC', '', $row['upc'])));
if (is_array($lcRow)) {
$lcName = $lcRow['likeCodeDesc'];
$organic = $lcRow['organic'] ? true : false;
}
}
$par = $this->connection->getValue($parP, array($store, $row['upc']));
if ($row['caseSize'] && ($par / $row['caseSize']) < 0.1) {
$par = 0.1 * $row['caseSize'];
}
// reset case size *after* setting min par at 0.1 standard cases
$row['realSize'] = $row['caseSize'];
$row['caseSize'] = 1;
$price = $this->connection->getValue($priceP, array(substr($row['upc'], 2)));
$cost = $this->connection->getRow($costP,
array(isset($row['lookupID']) ? $row['lookupID'] : $row['vendorID'], $row['vendorSKU']));
if ($cost && $cost['units'] > 1 && $cost['units'] != $row['caseSize']) {
$cost['cost'] /= $cost['units'];
}
if (!$cost) {
$cost = array('cost' => $row['cost'] / $row['caseSize'], 'units' => $row['caseSize']);
}
$onSale = $this->connection->getValue($saleP, array($row['upc'], $store));
$startIcon = '';
$starting = $this->connection->getValue($startingP, array($row['upc'], $store));
if ($starting) {
$startIcon = sprintf('<span class="glyphicon glyphicon-arrow-up" title="%s" />',
'Sale ' . ($onSale ? 'started' : 'starting') . ' on ' . $starting);
}
$endIcon = '';
$ending = $this->connection->getValue($endingP, array($row['upc'], $store));
if ($ending) {
$endIcon = sprintf('<span class="glyphicon glyphicon-arrow-down" title="%s" />',
'Sale ' . ($onSale ? 'ending' : 'ended') . ' on ' . $ending);
}
$upc = $row['upc'];
if (substr($row['upc'], 0, 2) == 'LC') {
$row['upc'] = sprintf('<a href="../../../item/likecodes/LikeCodeEditor.php?start=%d">%s</a>',
substr($row['upc'], 2), $row['upc']);
}
$orderAmt = '';
/** no auto-fill on direct
$start = $par;
while ($start > (0.25 * $row['caseSize'])) {
$orderAmt++;
$start -= $row['caseSize'];
if ($orderAmt > 500) {
echo $row['upc'] . ": $par, {$row['caseSize']}<br />";
break;
}
}
*/
$inOrder = $this->connection->getRow($inOrderP, array_merge($ioArgs, array($upc)));
if ($inOrder) {
$orderAmt = $inOrder['quantity'];
}
$farm1 = $this->connection->getValue($primaryP, array(date('Y-m-d'), $likeCode));
$opt1 = '<option></option>';
foreach ($farms as $f) {
$opt1 .= sprintf('<option %s value="%d">%s</option>',
($farm1 && $farm1 == $f['rpFarmID'] ? 'selected' : ''),
$f['rpFarmID'], $f['name']);
}
$farm2 = $this->connection->getValue($secondaryP, array(date('Y-m-d'), $likeCode));
$opt2 = '<option></option>';
foreach ($farms as $f) {
$opt2 .= sprintf('<option %s value="%d">%s</option>',
($farm2 && $farm2 == $f['rpFarmID'] ? 'selected' : ''),
$f['rpFarmID'], $f['name']);
}
$row['vendorName'] = str_replace(' (Produce)', '', $row['vendorName']);
$row['backupVendor'] = str_replace(' (Produce)', '', $row['backupVendor']);
$highlight = '';
$tooltip = '';
if ($onSale) {
$highlight = 'rp-success';
$tooltip = "On sale through {$onSale}";
} elseif (!$organic) {
$highlight = 'alert-warning';
$tooltip = 'Conventional';
}
$nextRow = sprintf('<tr class="%s">
<td class="upc %s">%s %s</td>
<td class="%s"><select class="primaryFarm form-control input-sm" data-default="%s" id="pf%s" onchange="rpOrder.updateFarm(this);">%s</option></td>
<td class="%s"><select class="secondaryFarm form-control input-sm" id="sf%s" onchange="rpOrder.updateFarm(this);">%s</option></td>
<td class="%s" title="%s">$%.2f %s %s %s%s</td>
<td style="display:none;" class="caseSize">%s</td>
<td style="display:none;" class="realSize">%s</td>
<td><input %s class="form-control input-sm onHand" value=""
style="width: 5em;" id="onHand%s" data-incoming="0"
onchange="rpOrder.reCalcRow($(this).closest(\'tr\')); rpOrder.updateOnHand(this);"
onfocus="this.select();" onkeyup="rpOrder.onHandKey(event);" />
<span class="incoming-notice"></span></td>
<input type="hidden" class="price" value="%.2f" />
<input type="hidden" class="basePar" value="%.2f" />
<td class="parCell">%.2f</td>
<td class="form-inline %s">
<input %s style="width: 5em;"class="form-control input-sm orderAmt"
id="orderAmt%s" onkeyup="rpOrder.orderKey(event); rpOrder.updateOrder(this);"
onfocus="this.select();" value="%s" />
<label><input type="checkbox" onchange="rpOrder.placeOrder(this);" value="%s,%d,%d" %s
class="orderPri" tabindex="-1" /> Pri</label>
</td>
<td class="form-inline %s">
<input %s style="width: 5em;"class="form-control input-sm secondAmt"
id="secondAmt%s" onkeyup="rpOrder.secondaryKey(event); rpOrder.updateOrder(this);"
onfocus="this.select();" value="%s" />
<label><input type="checkbox" onchange="rpOrder.placeOrder(this);" value="%s,%d,%d" %s
class="orderSec" tabindex="-1" /> Sec</label>
</td>
</tr>',
(in_array($likeCode, $directLCs) && $row['vendorID'] != -2 && $row['backupID'] != -2) ? 'extraLocal' : '',
$highlight, $row['upc'], $lcName,
$highlight,
$farm1, $upc,
$opt1,
$highlight,
$upc, $opt2,
$highlight,
$tooltip,
$cost['cost'] * $row['caseSize'],
($row['vendorSKU'] ? '(' . $row['vendorSKU'] . ')' : ''),
$row['vendorItem'],
$startIcon, $endIcon,
$row['caseSize'],
$row['realSize'],
$fieldType,
$upc,
$price,
$par,
$par / $row['caseSize'],
($inOrder ? 'info' : ''),
$fieldType,
$upc,
$orderAmt,
$upc, $store, $row['vendorID'],
($inOrder && $inOrder['vendorID'] == $row['vendorID'] ? 'checked' : ''),
'', // in secondary order ($inOrder ? 'info' : ''),
$fieldType,
$upc,
'', // secondary order amount
$upc, $store, $row['backupID'],
($inOrder && $inOrder['vendorID'] == $row['backupID'] && $row['backupID'] != null ? 'checked' : '')
);
if ($appendTables) {
$tables .= $nextRow;
} else {
$hiddenItems .= $nextRow;
}
}
$tables .= '</table>';
$tables .= '<table style="display:none;">'
. $hiddenItems
. '</table>';
$ts = time();
while (date('N', $ts) != 1) {
$ts = mktime(0, 0, 0, date('n', $ts), date('j',$ts) - 1, date('Y', $ts));
}
$weekStart = date('Y-m-d', $ts);
$weekP = $this->connection->prepare("SELECT * FROM RpSegments WHERE startDate=? AND storeID=?");
$projected = 'n/a';
$baseRetain = 60;
$days = array(
'Mon' => 'n/a',
'Tue' => 'n/a',
'Wed' => 'n/a',
'Thu' => 'n/a',
'Fri' => 'n/a',
'Sat' => 'n/a',
'Sun' => 'n/a',
);
$week = $this->connection->getRow($weekP, array($weekStart, $store));
$modProj = 0;
if ($week) {
$projected = number_format($week['sales']);
$baseRetain = $week['retention'];
$days = json_decode($week['segmentation'], true);
$days = array_map(function ($i) { return sprintf('%.2f%%', $i*100); }, $days);
$thisYear = json_decode($week['thisYear'], true);
$thisYear = is_array($thisYear) ? $thisYear : array();
$lastYear = json_decode($week['lastYear'], true);
$sums = array('this' => 0, 'last' => 0, 'proj' => 0);
$dataPoints = 0;
foreach ($thisYear as $key => $val) {
if ($val > 0 && $lastYear[$key] > 0) {
$sums['this'] += $val;
$sums['last'] += $lastYear[$key];
$sums['proj'] += str_replace(',', '', $projected) * (str_replace('%', '', $days[$key]) / 100.00);
$dataPoints++;
}
}
if ($dataPoints > 0) {
$growth = ($sums['this'] - $sums['proj']) / $sums['proj'];
$growth *= ($dataPoints / 7);
foreach ($days as $day) {
$val = str_replace(',', '', $projected) * (str_replace('%', '', $day) / 100.00);
$modProj += ($val * (1 + $growth));
}
/*
foreach ($lastYear as $key => $val) {
$modProj += ($val * (1 + $growth));
}
*/
$modProj = round($modProj, 2);
}
}
$mStamp = date('N') == 1 ? strtotime('today') : strtotime('last monday');
$dateIDs = array();
for ($i=0; $i<7; $i++) {
$dateIDs[] = date('Ymd', mktime(0,0,0,date('n',$mStamp),date('j',$mStamp)+$i,date('Y',$mStamp)));
}
$cats = new RpOrderCategoriesModel($this->connection);
$catOpts = $cats->toOptions();
$farms = new RpFarmsModel($this->connection);
$farmOpts = $farms->toOptions();
$autoOrder = 'checked';
if (COREPOS\Fannie\API\lib\Store::getIdByIp() == 2) {
$autoOrder = '';
}
return <<<HTML
<div class="row">
<div class="col-sm-6">
<p class="form-inline">
<label>Store</label>: {$sSelect['html']}
<label>Projected Sales this Week</label>:
<a href="RpSegmentation.php" id="projSales">{$projected}</a>
|
<a href="RpFileManager.php">RP Data</a>
<fieldset>
<label title="{$days['Mon']}"><input type="checkbox" class="daycheck"
data-dateid="{$dateIDs[0]}"
onchange="rpOrder.updateDays();" value="{$days['Mon']}" /> Monday</label>
<label title="{$days['Tue']}"><input type="checkbox" class="daycheck"
data-dateid="{$dateIDs[1]}"
onchange="rpOrder.updateDays();" value="{$days['Tue']}" /> Tuesday</label>
<label title="{$days['Wed']}"><input type="checkbox" class="daycheck"
data-dateid="{$dateIDs[2]}"
onchange="rpOrder.updateDays();" value="{$days['Wed']}" /> Wednesday</label>
<label title="{$days['Thu']}"><input type="checkbox" class="daycheck"
data-dateid="{$dateIDs[3]}"
onchange="rpOrder.updateDays();" value="{$days['Thu']}" /> Thursday</label>
<label title="{$days['Fri']}"><input type="checkbox" class="daycheck"
data-dateid="{$dateIDs[4]}"
onchange="rpOrder.updateDays();" value="{$days['Fri']}" /> Friday</label>
<label title="{$days['Sat']}"><input type="checkbox" class="daycheck"
data-dateid="{$dateIDs[5]}"
onchange="rpOrder.updateDays();" value="{$days['Sat']}" /> Saturday</label>
<label title="{$days['Sun']}"><input type="checkbox" class="daycheck"
data-dateid="{$dateIDs[6]}"
onchange="rpOrder.updateDays();" value="{$days['Sun']}" /> Sunday</label>
</fieldset>
<label title="Based on sales growth so far this week">Modified Projection</label>:
<span id="modProj">{$modProj}</span>
<br />
<label>Projected Sales these Days</label>:
<span id="selectedSales">0</span>
<br />
<label>Retail x Expected Movement</label>:
<span id="guessRetail">0</span>
<br />
<label>Adjustment</label>:
<span id="adjDiff">0</span>
<div class="form-inline">
<div class="input-group">
<span class="input-group-addon">Retention</span>
<input type="number" disabled value="{$baseRetain}" id="retention" class="form-control input-sm" />
<span class="input-group-addon">%</span>
</div>
</div>
<div class="form-inline">
<div class="input-group">
<span class="input-group-addon">Single Farm</span>
<select onchange="rpOrder.defaultFarm(this.value);" class="form-control">
<option></option>
{$farmOpts}
</select>
</div>
</div>
<div class="form-group">
<label title="Show only items currently set to DIRECT">
<input type="checkbox" onchange="if (this.checked) $('tr.extraLocal').hide(); else $('tr.extraLocal').show();" />
Limited List
</label>
</div>
<p>
<ul id="openOrders">{$orderLinks}</ul>
<span id="printLink">{$printLink}</span>
</p>
</p>
</div>
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">Add Item</div>
<div class="panel-body">
<form method="post">
<input type="hidden" name="store" value="{$store}" />
<div class="form-group input-group">
<span class="input-group-addon">Vendor</span>
<select name="vendor" class="form-control input-sm" required
id="newVendor" onchange="rpOrder.setSearchVendor(this.value);">
<option value=""></option>
<option value="292">Alberts</option>
<option value="293">CPW</option>
<option value="136">RDW</option>
<option value="358">KeHE</option>
<option value="1">UNFI</option>
<option value="-2">Direct</option>
</select>
</div>
<div class="form-group input-group">
<span class="input-group-addon">Item</span>
<input type="text" class="form-control input-sm" name="item" required id="newItem" />
</div>
<div class="col-sm-6">
<div class="form-group input-group">
<span class="input-group-addon">Likecode</span>
<input type="text" class="form-control input-sm" name="lc" id="newLC" />
</div>
</div>
<div class="col-sm-6">
<div class="form-group input-group">
<span class="input-group-addon">or UPC</span>
<input type="text" class="form-control input-sm" name="upc" id="newUPC" />
</div>
</div>
<div class="col-sm-6">
<div class="form-group input-group">
<span class="input-group-addon">SKU</span>
<input type="text" class="form-control input-sm" name="sku" id="newSKU" />
</div>
</div>
<div class="col-sm-6">
<div class="form-group input-group">
<span class="input-group-addon">Case Size</span>
<input type="text" class="form-control input-sm" name="caseSize" required id="newCase" />
</div>
</div>
<div class="form-group input-group">
<span class="input-group-addon">Category</span>
<select name="catID" class="form-control input-sm" required>{$catOpts}</select>
</div>
<button type="submit" class="btn btn-default">Add Item</button>
<button type="reset" class="btn btn-default btn-reset">Clear</button>
</form>
</div>
</div>
</div>
</div>
<p>
<div class="form-group">
<label>
<input type="checkbox" {$autoOrder} id="autoOrderCheck" />
Auto-fill order amounts
</label>
</div>
<button class="btn btn-default orderAll" onclick="rpOrder.orderAll();">Order All</button>
<a href="RpOrderPage.php" class="btn btn-default">Switch to Regular</a>
<div class="progress collapse">
<div class="progress-bar progress-bar-striped active" role="progressbar"
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%">
<span class="sr-only">Searching</span>
</div>
</div>
</p>
{$tables}
<p>
<button class="btn btn-default orderAll" onclick="rpOrder.orderAll();">Order All</button>
<a href="RpOrderPage.php" class="btn btn-default">Switch to Regular</a>
<div class="progress collapse">
<div class="progress-bar progress-bar-striped active" role="progressbar"
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%">
<span class="sr-only">Searching</span>
</div>
</div>
<br />
</p>
<p>
<ul id="altOpenOrders">{$orderLinks}</ul>
<span id="altPrintLink">{$printLink}</span>
</p>
<hr />
<p>
<a href="RpDirectPage.php?clear=1" class="btn btn-default">Clear Session Data</a>
</p>
HTML;
}
protected function css_content()
{
return <<<CSS
.rp-success {
background-color: #f772d2;
}
.table-striped>tbody>tr:nth-child(odd)>td.rp-success {
background-color: #f772d2;
}
.incoming-notice {
font-weight: bold;
color: #15AF23;
}
CSS;
}
}
FannieDispatch::conditionalExec();