CORE-POS/IS4C

View on GitHub
fannie/item/ProdReviewPage.php

Summary

Maintainability
F
1 wk
Test Coverage
F
33%
<?php
/*******************************************************************************

    Copyright 2017 Whole Foods Community Co-op

    This file is part of CORE-POS.

    CORE-POS 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.

    CORE-POS 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

*********************************************************************************/

use COREPOS\Fannie\API\lib\Operators as Op;

require(dirname(__FILE__) . '/../config.php');
if (!class_exists('FannieAPI')) {
    include(__DIR__ . '/../classlib2.0/FannieAPI.php');
}

class ProdReviewPage extends FannieRESTfulPage
{
    protected $must_authenticate = True;
    protected $auth_classes = array('admin');

    protected $header = 'Vendor Product Info Review';
    protected $title = 'Vendor Product Info Review';

    public $description = '[Vendor Product Info Review] keep a record of the
        last time product info was verified/updated for individual products.';

    function preprocess()
    {
        $this->__routes[] = 'get<upc>';
        $this->__routes[] = 'get<upc><save>';
        $this->__routes[] = 'get<list>';
        $this->__routes[] = 'get<list><save>';
        $this->__routes[] = 'get<vendor>';
        $this->__routes[] = 'get<vendor><checked>';
        $this->__routes[] = 'get<batchLog>';
        $this->__routes[] = 'get<batchLog><add>';
        $this->__routes[] = 'post<batchLog><force>';
        $this->__routes[] = 'get<batchLog><print>';
        $this->__routes[] = 'get<batchLog><printAll>';
        $this->__routes[] = 'get<batchLog><deleteRow><id>';
        $this->__routes[] = 'get<schedule>';
        $this->__routes[] = 'get<schedule><setup>';
        $this->__routes[] = 'get<schedule><setup><save>';
        $this->__routes[] = 'get<stagedReview>';
        return parent::preprocess();
    }

    public function get_stagedReview_view()
    {

        return <<<HTML
<form action=VendorPricingBatchPage.php method="get" target="_blank">
<input name="id" class="hidden" value="1">
<label>Forced date begin</label>
<input type="date" class="form-control">
<label>Forced date end</label>
<input type="date" class="form-control">
<br />
<p>
<button type=submit class="btn btn-default">Continue</button>
</p>
</form>
HTML;
    }

    public function get_schedule_setup_save_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $vid = FormLib::get('vid');
        $rate = FormLib::get('rate');

        if ($rate) {
            $args = array($rate,$vid);
            $prep = $dbc->prepare("UPDATE vendorReviewSchedule SET rate = ?, exclude = 0 WHERE vid = ?");
        } else {
            $args = array($vid);
            $prep = $dbc->prepare("UPDATE vendorReviewSchedule SET rate = 0, exclude = 1 WHERE vid = ?");
        }
        $dbc->execute($prep,$args);

        header('location: ProdReviewPage.php?schedule=1&setup=1');
    }

    public function backBtn()
    {
        return <<<HTML
<form name="backbutton">
<button class="btn btn-xs btn-primary backBtn" type="submit">
    <span class="fas fa-chevron-left"></span></button>
</form>
HTML;
    }

    public function get_schedule_setup_view()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);

        $ret = $this->backBtn()."<br/><br/>";
        $tableA = "<table class=\"table table-bordered table-condensed\">
            <thead><th>VID</th><th>Vendor</th><th>Rate</th><th>Excluded</th></thead><tbody>";
        $prep = $dbc->prepare("SELECT s.vid,s.rate,v.vendorName,s.exclude
            FROM vendorReviewSchedule AS s
            LEFT JOIN vendors AS v ON s.vid=v.vendorID WHERE v.inactive = 0
            ORDER BY exclude DESC, rate DESC, vendorID ASC,vendorName;");
        $res = $dbc->execute($prep);
        $tableA .= "<form class=\"form-inline\">";
        while ($row = $dbc->fetchRow($res)) {
            $vid = $row['vid'];
            $rate = $row['rate'];
            $class = ($row['exclude'])? 'alert-danger' : '';
            $tableA .= "<tr class='$class'><td>{$vid}</td>";
            $tableA .= "<td>{$row['vendorName']}</td>";
            $tableA .= "<td>
                <a href=\"#\" onClick=\"setRate({$vid},{$rate});\" id=\"{$vid}vid\">{$rate}</a>
                </td>";
            $tableA .= "<td>{$row['exclude']}</td></tr>";
        }
        $tableA .= "</tbody></table></form>";

        $modRate = "
            <div class='modal' id='rateModal'>
                <div class='modal-dialog vertical-alignment-helper'>
                    <div class='vertical-align-center'>
                        <div class='modal-content input-content'>
                                <div style='padding: 25px; padding-bottom: 5px'>
                                    <b>Rate</b> is the number of months in a year a vendor
                                        should be reviewed. Set a vendor's rate to 0 to exclude it from
                                        the Vendor Review Schedule.<br/><br/>
                                </div>
                            <div align='center'>
                                <form class='form-inline'>
                                    <input type='hidden' name='schedule' value='1'>
                                    <input type='hidden' name='setup' value='1'>
                                    <input type='hidden' name='save' value='1'>
                                    <input type='hidden' name='vid' id='vid' value='NULL'>
                                    <div class='input-group'>
                                        <span class='input-group-addon'>Rate (review every x month)</span>
                                        <input type='number' class='form-control' name='rate' id='rate'
                                            min='0' max='12' value='NULL'>
                                    </div>
                                    <div class='input-group'>
                                        <button type='submit' class='btn btn-default'>"
                                        . COREPOS\Fannie\API\lib\FannieUI::saveIcon() .
                                        "</span></button>
                                    </div>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        ";

        $ret .= $tableA;
        return <<<HTML
{$modRate}
{$ret}
HTML;
    }

    public function get_schedule_view()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);

        $prep = $dbc->prepare("
            SELECT p.upc, p.default_vendor_id, r.reviewed
            FROM products AS p
                LEFT JOIN prodReview AS r ON p.upc=r.upc
                INNER JOIN MasterSuperDepts AS m ON p.department=m.dept_ID
                LEFT JOIN vendorReviewSchedule AS v ON p.default_vendor_id=v.vid
            WHERE p.inUse = 1
                AND m.superID in (1,4,5,8,9,13,17,3,18)
                AND v.exclude <> 1
            GROUP BY p.upc
        ");
        $res = $dbc->execute($prep);
        $data = array();
        while ($row = $dbc->fetchRow($res)) {
            $data[$row['default_vendor_id']][$row['upc']] = $row['reviewed'];
        }

        $vprep = $dbc->prepare("
            SELECT v.vendorID, v.vendorName, s.rate, s.priority
            FROM vendors AS v
                LEFT JOIN vendorItems AS p ON v.vendorID=p.vendorID
                LEFT JOIN prodReview AS r ON r.upc=p.upc
                LEFT JOIN vendorReviewSchedule AS s ON v.vendorID=s.vid
            WHERE inactive = 0
            GROUP BY p.vendorID
        ");
        $vres = $dbc->execute($vprep);
        while ($row = $dbc->fetchRow($vres)) {
            $rate = $row['rate'] == 0 ? 0 : 12 / $row['rate'];
            $y = date('Y');
            $m = date('m');
            $m -= $rate;
            if ($m <= 0) {
                $m = 12 + $m;
                $y--;
            }
            $d = date('d');
            $data[$row['vendorID']]['rate'] = $y."-".$m."-".$d;
            $data[$row['vendorID']]['name'] = $row['vendorName'];
            $data[$row['vendorID']]['vid'] = $row['vendorID'];
        }

        $vendorinfo = '';
        foreach ($data as $vid => $row) {
            if (empty($data[$vid]['good'])) {
                $data[$vid]['good'] = 0;
            }
            if (empty($data[$vid]['total'])) {
                $data[$vid]['total'] = 0;
            }
        }
        foreach ($data as $vid => $row) {
            foreach ($row as $upc => $review) {
                if (is_numeric($upc)) {
                    $data[$vid]['total']++;
                    if (strtotime($review) ) {
                        $reviewUTS = strtotime($review);
                        $rateUTS = !isset($data[$vid]['rate']) ? 0 : strtotime($data[$vid]['rate']);
                        if ($reviewUTS > $rateUTS) {
                            $data[$vid]['good']++;
                        }
                    }
                }
            }
        }
        foreach ($data as $vid => $row) {
            $data[$vid]['priority'] = Op::div($row['good'], $row['total']);
            $data[$vid]['score'] = Op::div($row['good'], $row['total']);
            if ($data[$vid]['priority'] == 0) {
                $data[$vid]['priority'] = 1.01;
            }
        }
        usort($data, function($a, $b) {
            if ($a["priority"] == $b["priority"]) return 0;
            return $a["priority"] > $b["priority"] ? 1 : -1;
        });

        $table = "<table class='table table-condensed table-bordered table-striped small tablesorter tablesorter-bootstrap' id='reviewtable'>
            <thead><th>VID</th><th>Vendor</th><th>Priority</th><th>ProdCount</th><th>% Reviewed</th></thead><tbody>";
        $vExclude = array(NULL,-1,1,2,242,70);
        foreach ($data as $k => $v) {
            if (isset($v['vid']) && !in_array($v['vid'],$vExclude)) {
                if ($v["priority"] == 1.01) {
                    $v["score"] = 0;
                    $n = 0;
                    $re = 0;
                } else {
                    $n = $v["priority"];
                    $re = 1 - $n;
                    $n *= 100;
                    $re *= 100;
                    $n = round($n);
                    $re = round($re);
                    $r = (255 * $n);
                    $g = (255 - (100 * $n));
                    $b = 0;
                }
                if (!isset($color)) {
                    $color = '';
                }
                $grade = "<span style='font-size: 10px; height: 15px; width: 90%;
                    color: {$color}; float: left; text-align: center;
                    background: linear-gradient(to right, lightgreen $n%, 1%, tomato $re%);'>
                    </span>
                    ";
                $score = sprintf("%d%%",$v['score']*100);
                $vid = $v['vid'];
                if ($v['total'] > 0) {
                    $table .= "<tr><td class='vid'>{$vid}</td>";
                    $table .= "<td>{$v['name']}</td>";
                    $table .= "<td>{$grade}</td>";
                    $table .= "<td>{$v['total']}</td>";
                    $table .= "<td>{$score}</td>";
                }
            }
        }
        $table .= "</tbody></table>";

        $this->addScript('../src/javascript/tablesorter-2.22.1/js/jquery.tablesorter.js');
        $this->addScript('../src/javascript/tablesorter-2.22.1/js/jquery.tablesorter.widgets.js');
        $this->addOnloadCommand("$('#reviewtable').tablesorter({theme:'bootstrap', headerTemplate: '{content} {icon}', widgets: ['uitheme','zebra']});");

        return <<<HTML
{$this->backBtn()}<br/>
<a href="ProdReviewPage.php?schedule=1&setup=1">Vendor Setup</a>
<br/><br/>
{$table}
HTML;
    }

    public function get_batchLog_deleteRow_id_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $bid = FormLib::get('id');
        $args = array($bid);
        $prep = $dbc->prepare("DELETE FROM batchReviewLog WHERE bid= ?");
        $dbc->execute($prep,$args);

        return header('location: '.$_SERVER['PHP_SELF'].'?batchLog=1');
    }

    public function get_batchLog_printAll_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $prep = $dbc->prepare("UPDATE batchReviewLog SET printed = 1 WHERE printed = 0");
        $dbc->execute($prep);

        return header('location: '.$_SERVER['PHP_SELF'].'?batchLog=1');
    }

    public function get_batchLog_add_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $bid = FormLib::get('bid');

        $getA = array($bid);
        $getP = $dbc->prepare("
            SELECT bl.*, p.default_vendor_id AS vid,
                v.vendorName, b.batchName
            FROM batchList AS bl
                LEFT JOIN products AS p ON bl.upc=p.upc
                LEFT JOIN vendors AS v ON p.default_vendor_id=v.vendorID
                LEFT JOIN batches AS b ON bl.batchID=b.batchID
            WHERE bl.batchID = ?;");
        $getR = $dbc->execute($getP,$getA);
        $firstItr = 0;
        while ($row = $dbc->fetchRow($getR)) {
            if ($firstItr === 0) {
                $first = $row['vid'];
                $vid = $row['vid'];
            }
            $temp = $row['vid'];
            if ($temp != $first) {
                $vid = 0;
            }
        }
        if ($vid == 0) {
            $vid  = "n/a";
        }
        $user = FannieAuth::getUID($this->current_user);
        $model = new BatchReviewLogModel($dbc);
        $model->bid($bid);
        $model->vid($vid);
        $model->printed(0);
        $model->user($user);
        $model->created(date('Y-m-d H:i:s'));
        $model->forced(0);
        $model->save();

        return header('location: '.$_SERVER['PHP_SELF'].'?batchLog=1');
    }

    public function post_batchLog_force_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $bid = FormLib::get('bid');
        $user = FannieAuth::getUID($this->current_user);
        if ($user == 0 || empty($user)) {
            $user = 'unknown';
        }

        $b = new BatchesModel($dbc);
        $b->forceStartBatch($bid);

        $args = array($user,$bid);
        $prep = $dbc->prepare("UPDATE batchReviewLog SET forced = NOW(), user = ? WHERE bid = ?");
        $dbc->execute($prep,$args);
        $json = array('error'=>false, 'success'=>false);
        if ($er = $dbc->error()) {
            $json['error'] = $er;
        } else {
            $json['success'] = true;
        }
        echo json_encode($json);

        return false;
    }

    public function get_batchLog_print_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $bid = FormLib::get('bid');

        $args = array($bid);
        $prep = $dbc->prepare("UPDATE batchReviewLog SET printed = 1 WHERE bid = ?");
        $dbc->execute($prep,$args);

        return header('location: '.$_SERVER['PHP_SELF'].'?batchLog=1');
    }

    private function getBatchItemDiscrep($dbc)
    {
        $found = array();
        $tmp = array();
        $prep = $dbc->prepare("SELECT * from batchReviewLog AS l
            INNER JOIN batchList AS b ON b.batchID=l.bid WHERE forced = 0;");
        $res = $dbc->execute($prep);
        while ($row = $dbc->fetchRow($res)) {
            $upc = $row['upc'];
            $batchID = $row['batchID'];
            $tmp[$upc][] = $batchID;
        }
        foreach ($tmp as $upc => $array) {
            if (count($array) > 1) {
                foreach ($array as $batchID) {
                    $found[$batchID][] = $upc;
                }
            }
        }

        return $found;
    }

    public function get_batchLog_view()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);

        /*
            tableA = unforced batches | tableB = forced.
        */
        $bids = "0";
        $pAllBtn = "<button class='btn btn-default btn-xs'
            onClick='printAll(); return false;'><span class='fas fa-print'></span></button>";
        $tableA = "<div class='table-responsive'><table class='table table-condensed table-striped small'><thead><tr class=\"thead\">
            <th>{$pAllBtn}</th>
            <th>BatchID</th><th>Batch Name</th><th>Super Depts +</th><th>VID</th><th>Vendor</th><th>Uploaded</th>
            <th>Comments</th><th></th><th></th><tr></thead><tbody>";
        $tableB = "<div class='table-responsive'><table class='table table-condensed table-striped small' id='forcedBatchesTable'><thead><tr class=\"thead\">
            <th>BatchID</th><th>Batch Name</th><th>Super Depts +</th><th>VID</th><th>Vendor</th><th>Forced On</th>
            <th>user</th><tr></thead><tbody>";
        $args = array();
        $prep = $dbc->prepare("
            SELECT l.vid, l.printed, l.user, l.created, l.forced,
                b.batchName, l.bid, v.vendorName, l.comments, u.name, m.super_name, s.plu
            FROM batchReviewLog AS l
                LEFT JOIN batches AS b ON l.bid=b.batchID
                LEFT JOIN batchList AS bl ON b.batchID=bl.batchID
                LEFT JOIN products AS p ON p.upc=bl.upc
                LEFT JOIN MasterSuperDepts AS m ON p.department=m.dept_ID
                LEFT JOIN vendors AS v ON l.vid=v.vendorID
                LEFT JOIN Users AS u ON l.user=u.uid
                LEFT JOIN scaleItems AS s ON bl.upc=s.plu
            WHERE forced > NOW() - INTERVAL 3 MONTH 
                OR forced = 0
            GROUP BY l.bid, m.super_name
            ORDER BY l.forced DESC, l.bid DESC
        ");
        $res = $dbc->execute($prep,$args);
        $batches = array();
        while ($row = $dbc->fetchRow($res)) {
            if (!isset($batches[$row['bid']])) {
                $batches[$row['bid']] = array();
            }
            if (!in_array($row['super_name'], $batches[$row['bid']])) {
                $batches[$row['bid']][] = $row['super_name'];
            }
        };

        $discr = $this->getBatchItemDiscrep($dbc);
        
        $res = $dbc->execute($prep,$args);
        $curBid = -999;
        while ($row = $dbc->fetchRow($res)) {
            $scale = '';
            $superDepts = '';
            if ($row['bid'] == $curBid)
                continue;
            $curBid = $row['bid'];
            foreach ($batches[$curBid] as $k => $superName) {
                $rgb = '#'.substr(md5($superName), 0, 6);
                $superDepts .= "<span class=\"supertab\" title=\"$superName\" style=\"color: $rgb;\">".substr($superName,0,4)."</span>";
            }
            if ($scale == '' && $row['plu'] != NULL)
                $superDepts .= "<span class=\"\" style=\"border: 1px solid black; border-radius: 50%; padding-left: 3px; padding-right: 3px; cursor: default;\" title=\"Scale Items in batch\">S</span>";
            $curDiscr = '';
            if (array_key_exists($curBid, $discr)) {
                $title = '';
                foreach ($discr[$curBid] as $upc) {
                    $title .= <<<HTML
<div>$upc</div>
HTML;
                }
                $curDiscr = ' <a href="#" class="btn btn-xs btn-danger showDiscrFound" title="'.$title.'"><span class="fas fa-exclamation-circle"></span></a>';
            }
            $curBidLn = "../batches/newbatch/EditBatchPage.php?id=".$curBid;
            if ($row['forced'] == '0000-00-00 00:00:00') {
                $bids .= ",".$curBid;
                $tableA .= "<tr>";
                $tableA .= "<td><input type='checkbox' id='check$curBid' class='upcCheckBox'></td>";
                $tableA .= "<td class='biduf'><a href=\"{$curBidLn}\" target=\"_blank\">{$curBid}</a>$curDiscr</td>";
                $batchName = $row['batchName'];
                $tableA .= "<td>{$batchName}</td>";
                $tableA .= "<td class=\"super-depts\">$superDepts</td>";
                if ($row['vid'] == 0) {
                    $vid = "n/a";
                } else {
                    $vid = $row['vid'];
                }
                $tableA .= "<td>{$vid}</td>";
                $tableA .= "<td>{$row['vendorName']}</td>";
                $uploaded = substr($row['created'],0,10);
                $tableA .= "<td>{$uploaded}</td>";
                $tableA .= "<td><textarea name='comments' class='batchLogInput editable'
                    ' rows=2>{$row['comments']}</textarea></td>";
                $action = '';
                $noPunctBatchName = str_replace("'", "", $batchName);
                $action = "<td><button class='btn btn-default ' style='border: 1px solid tomato;'
                    onClick='forceBatch($curBid, \"$noPunctBatchName\"); return false;' id='force$curBid'>Force</button></td>";
                $tableA .= "<td><span class='fas fa-trash' onClick='deleteRow($curBid)' title='Remove from staging table'></span></td>";
                $tableA .= $action;
                $tableA .= "</tr>";
            } else {
                $tableB .= "<tr>";
                $tableB .= "<td class='bid'><a href=\"{$curBidLn}\" target=\"_blank\">{$curBid}</a></td>";
                $batchName = $row['batchName'];
                $tableB .= "<td>{$batchName}</td>";
                $tableB .= "<td>$superDepts</td>";
                $tableB .= "<td>{$row['vid']}</td>";
                $tableB .= "<td>{$row['vendorName']}</td>";
                $tableB .= "<td>{$row['forced']}</td>";
                $tableB .= "<td>{$row['user']} | {$row['name']}</td>";
                $tableB .= "</tr>";
            }
        }
        $tableA .= '</tbody></table></div>';
        $tableB .= '</tbody></table></div>';

        return <<<HTML
<div id="ajax-processing" style="text-align: center; position: fixed; top: 48vh; left: 40vw; font-weight: bold; background: rgba(255, 100, 100, 0.8); border: 3px solid pink; display: none;">BATCH BEING FORCED, PLEASE WAIT</div>
<div align="">
        <div class="">
            <div>{$this->backBtn()}</div>
        </div>
        <div class="row">
            <div class="col-lg-4">
                <form method="get" class="form-inline">
                    <div id="alert"><div id="resp"></div></div>
                </form>
            </div>
            <div class="col-lg-4"></div>
            <div class="col-lg-4">
                <label for="hide-deli-check">Hide Deli&nbsp;</label>
                <input type="checkbox" id="hide-deli-check" /> | 
                <label for="show-deli-check">Show Only Deli&nbsp;</label>
                <input type="checkbox" id="show-deli-check" /> |
                <label for="hide-wait-check">Hide Wait&nbsp;</label>
                <input type="checkbox" id="hide-wait-check" />
            </div>
        </div>
        <h4 align="center">Batches Staged for Price Changes</h4>
        <div class="batchTable">
            <div id="discrFound" style="padding: 15px;"></div>
            {$tableA}
        </div>
        <h4 align="center">History of Price Change Batches</h4>
        <div class="batchTable" >
            {$tableB}
        </div>
</div>
HTML;
    }

    public function get_vendor_checked_handler()
    {

        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $upcs = FormLib::get('checked');
        $user = FannieAuth::getUID($this->current_user);
        $vendorID = FormLib::get('vendorID');
        $pr = new ProdReviewModel($dbc);
        $data = array();
        $error = 0;
        foreach ($upcs as $upc) {
            $pr->reset();
            $pr->upc($upc);
            $pr->vendorID($vendorID);
            $pr->user($user);
            $pr->reviewed(date('Y-m-d'));
            if (!$pr->save()) {
                $error = 1;
            }
        }
        if (!$error) {
            header('Location: '.$_SERVER['PHP_SELF'].'?saved=true');
        } else {
            header('Location: '.$_SERVER['PHP_SELF'].'?saved=false');
        }

        return false;
    }

    public function get_vendor_view()
    {
        $vid = $this->vendor;
        $vendorID = FormLib::get('vendor');

        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $p = new ProductsModel($dbc);
        $p->default_vendor_id($vid);
        $p->inUse(1);

        $masterDepts = array(1,3,4,5,8,9,13,17,18);
        $curDepts = array();
        $m = new MasterSuperDeptsModel($dbc);
        foreach ($masterDepts as $mDept) {
            $m->reset();
            $m->superID($mDept);
            foreach ($m->find() as $obj) {
                $curDepts[] = $obj->dept_ID();
            }
        }

        $superNames = array();
        $superStrings = array();
        $prep = $dbc->prepare("
            SELECT super_name, dept_ID FROM MasterSuperDepts
        ");
        $r = $dbc->execute($prep);
        while ($row = $dbc->fetchRow($r)) {
            $superNames[$row['dept_ID']] = $row['super_name'];
        }

        foreach ($p->find() as $obj) {
            $dept = $obj->department();
            $name = $superNames[$dept];
            if (!in_array($name, $superStrings)) $superStrings[] = $name;
        }
        $vdepts = '<label>Super Departments</label><ul>';
        foreach ($superStrings as $name) {
            $vdepts .= "<li>$name</li>";
        }
        $vdepts .= '</ul>';

        $table = '<table class="table table-condensed small tablesorter tablesorter-bootstrap" id="reviewtable">';
        $table .= '<thead><th>UPC</th><th>Brand</th><th>Description</th>
            <th>Reviewed On</th></thead><tbody><td></td><td></td><td></td><td></td><td>
            <input type="checkbox" id="checkAll" class="upcCheckBox" style="border: 1px solid red;"></td>';

        $pr = new ProdReviewModel($dbc);
        $in = array();
        foreach ($p->find() as $obj) {
            if (!in_array($obj->upc(),$in) && in_array($obj->department(),$curDepts)) {
                $table .= '<tr>';
                $table .= '<td>'.$obj->upc().'</td>';
                $table .= '<td>'.$obj->brand().'</td>';
                $table .= '<td>'.$obj->description().'</td>';
                $pr->reset();
                $pr->upc($obj->upc());
                $pr->vendorID($obj->default_vendor_id());
                if ($pr->load()) {
                    $table .= '<td class="reviewed">'.$pr->reviewed().'</td>';
                } else {
                    $table .= '<td><i class="text-danger">no review date</i></td>';
                }
                $table .= '<td><input type="checkbox"class="chk upcCheckBox" name="checked[]" value="'.$obj->upc().'"></td>';
                $table .= '</tr>';
            }
            $in[] = $obj->upc();
        }
        $table .= '</tbody></table>';
        $this->addScript('../src/javascript/tablesorter-2.22.1/js/jquery.tablesorter.js');
        $this->addScript('../src/javascript/tablesorter-2.22.1/js/jquery.tablesorter.widgets.js');
        $this->addOnloadCommand("$('#reviewtable').tablesorter({theme:'bootstrap', headerTemplate: '{content} {icon}', widgets: ['uitheme','zebra']});");

        $model = new VendorsModel($dbc);
        $vselect = '';
        $exclude = array(-1,1,2);
        $curVendor = FormLib::get('vendor');
        foreach ($model->find('vendorName') as $obj) {
            if (!in_array($obj->vendorID(),$exclude)) {
                $vid = $obj->vendorID();
                $vname = $obj->vendorName();
                $sel = ($curVendor == $vid) ? ' selected' : '' ;
                $vselect .= '<option value="'.$vid.'" '.$sel.'>'.$vname.' - '.$vid.'</option>';
            }
        }
        $this->addOnloadCommand("
            $('#vselect').on('change', function(){
                document.forms['vform'].submit();
            });
        ");

        $vendor = new VendorsModel($dbc);
        $vendor->vendorID($curVendor);
        $vendor->load();
        $shipping = $vendor->shippingMarkup();
        if ($shipping > 0) {
            $shipping = $vendor->shippingMarkup() * 100;
            $shipping = "<label>Shipping Markup</label> $shipping%";
        } else {
            $shipping = '';
        }

        return <<<HTML
{$this->backBtn()}
<form class="form" method="get" name="vform">
    <div class="form-group">
    </div>
    <div class="form-group">
        <label>Review Products by Vendor</label>
        <select class="form-control" name="vendor" id="vselect">
            <option value="1">Select a Vendor</option>
            {$vselect}
        </select>
    </div>
</form>
<div>$shipping</div>
$vdepts
<form class="form-inline" id="review-form" name="review-form" method="get">
    {$table}
    <input type="hidden" name="vendor" value="1" />
    <input type="hidden" name="vendorID" value="$vendorID" />
    <a href="#" class="btn btn-warning" 
        onclick=" if ($('#review-form input:checkbox:checked').length > 0) { document.forms['review-form'].submit(); } else { return false; }">Set Checked Items As Reviewed</a>
</form><br />
HTML;
    }

    public function draw_table($data,$dbc)
    {
        $table = '<table class="table table-condensed table-striped small">';
        $table .= '<thead><th>UPC</th><th>Brand</th><th>Description</th>
            <th>Last Reviewed</th></thead><tbody>';

        $pP = $dbc->prepare("SELECT default_vendor_id FROM products WHERE upc = ?");
        $rP = $dbc->prepare("SELECT reviewed FROM prodReview WHERE upc = ? AND vendorID = ?"); 

        $p = new ProductsModel($dbc);
        $pr = new ProdReviewModel($dbc);
        $table .= '<tr>';
        foreach ($data as $upc => $arr) {
            foreach ($arr as $k => $v) {
                if ($k == 'upc') {
                    $vendorID = $dbc->getValue($pP, array($v));
                    $reviewed = $dbc->getValue($rP, array($v, $vendorID));
                    $table .= '<td>'.$v.'</td>';
                } elseif ($k == 'brand') {
                    $table .= '<td>'.$v.'</td>';
                } elseif ($k == 'description') {
                    $table .= '<td>'.$v.'</td>';
                    if ($reviewed != NULL) {
                        $table .= '<td>'.$reviewed.'</td>';
                    } else {
                        $table .= '<td><i>no review date</i></td>';
                    }
                    $table .= '</tr><tr>';
                }
            }

        }
        $table .= '</tr>';
        $table .= '</tbody></table>';

        return $table;
    }

    public function get_upc_view()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $upc = BarcodeLib::padUPC($this->upc);
        $p = new ProductsModel($dbc);
        $p->upc($upc);
        $p->store_id(1);
        $data = array();
        foreach ($p->find() as $obj) {
            $data[$upc]['upc'] = $obj->upc();
            $data[$upc]['brand'] = $obj->brand();
            $data[$upc]['description'] = $obj->description();
        }
        $table = $this->draw_table($data,$dbc);
        return <<<HTML
{$this->backBtn()}<br/><br/>
<form class="form-inline" method="get">
    {$table}
    <input type="hidden" name="upc" value="{$upc}">
    <input type="hidden" name="save" value="1">
    <input type="submit" class="btn btn-warning" value="Mark as Reviewed" />
</form><br />
HTML;

    }

    public function get_upc_save_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $upc = BarcodeLib::padUPC(FormLib::get('upc'));
        $user = FannieAuth::getUID($this->current_user);
        $pr = new ProdReviewModel($dbc);
        $pr->upc($upc);
        $pr->user($user);
        $pr->reviewed(date('Y-m-d'));
        if ($pr->save()) {
            header('Location: '.$_SERVER['PHP_SELF'].'?saved=true');
        } else {
            header('Location: '.$_SERVER['PHP_SELF'].'?saved=false');
        }

        return false;
    }

    public function get_list_save_handler()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);
        $upcs = FormLib::get('upcs');
        $user = FannieAuth::getUID($this->current_user);
        $vendor = FormLib::get('vendorToUpdate');
        $pm = new ProductsModel($dbc);
        //$pr = new ProdReviewModel($dbc);
        $data = array();
        $error = 0;

        $defP = $dbc->prepare("INSERT INTO prodReview (upc, user, reviewed, vendorID) values (?, ?, ?, ?) 
            ON DUPLICATE KEY UPDATE reviewed = ?");

        foreach ($upcs as $upc) {
            //$pr->reset();
            //$pr->upc($upc);
            //$pr->user($user);
            //$pr->reviewed(date('Y-m-d'));
            $now = date('Y-m-d');

            if ($vendor == 'default') {
                $pm->reset();
                $pm->upc($upc);
                $pm->load();
                $vid = $pm->default_vendor_id();
                //$pr->vendorID($vid);
                $defA = array($upc, $user, $now, $vid, $now);
                $defR = $dbc->execute($defP, $defA);
            } else {
                //$pr->vendorID($vendor);
                $defA = array($upc, $user, $now, $vendor, $now);
                $defR = $dbc->execute($defP, $defA);
            }

            //if (!$pr->save()) {
            //    $error = 1;
            //}
            $error = 0;
        }
        if (!$error) {
            header('Location: '.$_SERVER['PHP_SELF'].'?saved=true');
        } else {
            header('Location: '.$_SERVER['PHP_SELF'].'?saved=false');
        }


        return false;
    }

    public function get_list_view()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);

        $upcs = array();
        $plus = array();
        $chunks = explode("\r\n", $this->list);
        foreach ($chunks as $key => $str) {
            $upcs[] = BarcodeLib::padUPC($str);
        }
        $data = array();
        $p = new ProductsModel($dbc);
        $input = '';
        foreach ($upcs as $upc) {
            $p->reset();
            $p->upc($upc);
            foreach($p->find() as $obj) {
                $data[$upc]['upc'] = $obj->upc();
                $data[$upc]['brand'] = $obj->brand();
                $data[$upc]['description'] = $obj->description();
            }
            $input .= '<input type="hidden" name="upcs[]" value="'.$upc.'">';
        }
        $table = $this->draw_table($data,$dbc);

        $model = new VendorsModel($dbc);
        $vselect = '';
        $exclude = array(-1);
        foreach ($model->find('vendorName') as $obj) {
            if (!in_array($obj->vendorID(),$exclude)) {
                $vid = $obj->vendorID();
                $vname = $obj->vendorName();
                $vselect .= "<option value=\"$vid\">$vname - $vid</option>";
            }
        }

        $FANNIE_URL = $this->config->get('URL');
        $this->addScript($FANNIE_URL . 'src/javascript/chosen/chosen.jquery.min.js');
        $this->addCssFile($FANNIE_URL . 'src/javascript/chosen/bootstrap-chosen.css');

        $this->add_onload_command('$(\'.chosen-select:visible\').chosen();');
        $this->add_onload_command('$(\'#store-tabs a\').on(\'shown.bs.tab\', function(){$(\'.chosen-select:visible\').chosen();});');

        return <<<HTML
{$this->backBtn()}<br/><br/>
<form class="form-inline" method="get">
    <div class="form-group">
        <select class="form-control chosen-select" name="vendorToUpdate">
            <option value="default">Default Vendor ID</option> 
            $vselect
        </select>
    </div>
    {$table}
    {$input}
    <input type="hidden" name="list" value="1">
    <input type="hidden" name="save" value="1">
    <input type="submit" class="btn btn-warning" value="Mark as Reviewed" />
</form><br />
HTML;

    }

    function get_view()
    {
        global $FANNIE_OP_DB;
        $dbc = FannieDB::get($FANNIE_OP_DB);

        $model = new VendorsModel($dbc);
        $vselect = '';
        $exclude = array(-1,1,2);
        foreach ($model->find('vendorName') as $obj) {
            if (!in_array($obj->vendorID(),$exclude)) {
                $vid = $obj->vendorID();
                $vname = $obj->vendorName();
                $vselect .= '<option value="'.$vid.'">'.$vname.'</option>';
            }
        }

        $alert = '';
        if ($saved = FormLib::get('saved')) {
            if ($saved == 'false') {
                $alert = '<div class="alert alert-danger">Save Unsuccessful</div>';
            } else {
                $alert = '<div class="alert alert-success">Save Successful</div>';
            }
        }

        return <<<HTML
<div align="center">
    <div class="panel panel-default " style="max-width: 800px;">
    <div class="panel-heading">Product Review</div>
    <div class="panel-body" style="text-align: left;">
        {$alert}
        <div class="row">
            <div class="col-md-6">
                <form class="form" method="get">
                    <div class="form-group input-group-sm">
                        <label>Review a single UPC</label>
                        <div class="input-group">
                            <input type="text" class="form-control" name="upc" value="" autofocus>
                            <span class="input-group-addon">
                                <button class="input-addon-btn fas fa-chevron-right" type="submit">
                                </button>
                            </span>
                        </div>
                    </div>
                 </form>
                 <div class="divider"></div>
                <form class="form" method="get">
                    <div class="form-group">
                        <label>Review Products by Vendor</label>
                        <div class="input-group">
                            <select class="form-control" name="vendor">
                                <option value="1">Select a Vendor</option>
                                {$vselect}
                            </select>
                            <div class="input-group-addon">
                                <button class="input-addon-btn" type="submit">
                                    <span class="fas fa-chevron-right"></span>
                                </button>
                            </div>
                        </div>
                    </div>
                </form>
                <div class="divider hidden-md hidden-lg"></div>
            </div>
            <div class="col-md-6">
        <form class="form" method="get">
                <div class="form-group" style="z-index: -1">
                    <label>Review a list of UPCs</label>
                    <div class="input-group">
                    <textarea class="form-control" rows="5" name="list" style="z-index: 0"></textarea>
                    <span class="input-group-addon">
                    <button class="btn btn-default" type="submit"><span class="fas fa-chevron-right"></span></button>
                    </span>
                    </div>
                </div>
        </form>


            </div>

    </div>
</div>
</div>
    <div class="panel panel-default " style="max-width: 800px;">
        <div class="panel-body" style="text-align: left;">
            <div class="row">
                <div class="col-lg-4">
                    <label>Related Pages</label>
                    <ul>
                        <li><a href="ProdLocationEditor.php">Product <strong>Location</strong> Editor</a></li>
                        <li><a href="ProdReviewPage.php?batchLog=1">Review <strong>Batch Log</strong></a></li>
                    </ul>
                </div>
                <div class="col-lg-4">
                    <ul>
                        <li><a href="MultiMerchEditor.php">Products with <strong>Multiple Locations</strong></a></li>
                    </ul>
                </div>
                <div class="col-lg-4">
                    <ul>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>

HTML;

    }

   public function javascript_content()
   {
    return <<<JAVASCRIPT
var lastChecked = null;
var i = 0;
var indexCheckboxes = function(){
    // 1. unset all data-index
    $('.upcCheckBox').each(function(){
        $(this).attr('data-index', null);
    });

    // 2. set data-index if checkbox is visible
    $('.upcCheckBox').each(function(){
        if ($(this).is(":visible")) {
            $(this).attr('data-index', i);
            i++;
        }
    });
};
indexCheckboxes();
$('.upcCheckBox').on("click", function(e){
    if(lastChecked && e.shiftKey) {
        var i = parseInt(lastChecked.attr('data-index'));
        var j = parseInt($(this).attr('data-index'));
        var checked = $(this).is(":checked");

        var low = i;
        var high = j;
        if (i>j){
            var low = j;
            var high = i;
        }

        for(var c = low; c < high; c++) {
            if (c != low && c!= high) {
                var check = checked ? true : false;
                $('input[data-index="'+c+'"').prop("checked", check);
            }
        }
    }
    lastChecked = $(this);
});

$(document).ready( function() {
    $('#checkAll').click( function () {
       checkAll();
    });
    editable();
});

function deleteRow(id)
{
    var url = "ProdReviewPage.php?batchLog=1&deleteRow=1&id="+id;
    var c = confirm('Remove Batch From Table?');
    if (c == true) {
        window.open(url, '_self');
    }
}

function setRate(vid,rate)
{
    $('#vid').val(vid);
    $('#rate').val(rate);
    $('#rateModal').modal('show');

}

function printAll()
{
    var signUrl = "../admin/labels/SignFromSearch.php";
    var bids = [];
    var data = '?';
    var i = 0;
    $('input[type=checkbox]').each(function(){
        if ($(this).prop('checked')) {
            id = $(this).attr('id').substr(5);
            bids.push(id);
            console.log('checked: '+id);
        }
    });
    $.each(bids, function(k,v) {
        data = data.concat("batch[]="+v+"&");
    });
    data = data.slice(0,-1);
    window.open(signUrl+data, '_blank');

}

function checkAll()
{
    if ( $('#checkAll').prop("checked", true) ) {
        $('.chk').each( function() {
            this.checked = true;
        });
    } else {
        $('.chk').each( function() {
            this.checked = false;
        });
    }
}

function editable()
{
    $('.editable').change(function() {
        var path = window.location.pathname;
        var bid = $(this).closest('tr').find('a').text();
        var comment = $(this).closest('tr').find('.editable').val();
        $.ajax({
            type: 'post',
            url: 'ProdReviewRequest.php',
            data: 'bid='+bid+"&comment="+comment,
            success: function(resp) {
                $('#resp').html(resp);
                fadeAlerts();
            }
        })
    });
}

function forceBatch(bid, bname)
{
    buttonid = 'force'+bid;
    html = $('#'+buttonid).closest('tr').html();
    var conf = confirm("Force Batch "+bid+"?");
    if (conf) {
        $.ajax({
            type: 'post',
            data: 'bid='+bid+'&batchLog=1&force=1',
            dataType: 'json',
            beforeSend: function()
            {
                console.log('beforeSend successful');
                $('#ajax-processing').show();
            },
            success: function(json)
            {
                if (json.success == true) {
                    $('#'+buttonid).closest('tr').hide();
                    $('#forcedBatchesTable > tbody')
                        .prepend('<tr><td>'+bid+'</td><td>'+bname+'</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>');
                } else {
                    alert('Error: '+json.error);
                }
            },
            error: function(e)
            {
                alert('Request unsuccessful, see console.log for details.');
                console.log(e);
            },
            complete: function()
            {
                $('#ajax-processing').hide();
            }
        });
    }
}

function printBatch(bid)
{
    var signUrl = "../admin/labels/SignFromSearch.php";
    var data = "?batch[]="+bid;
    var conf = confirm("Print batch "+bid+"?");
    if (conf) {
        var path = window.location.pathname;
        window.open(signUrl+data, '_blank');
        window.location.href=path+"?bid="+bid+"&batchLog=1&print=1";
    }
}
function addBatch(bid)
{
    var path = window.location.pathname;
    window.location.href=path+"?bid="+bid+"&batchLog=1&add=1";
}

function fadeAlerts()
{
    $('.alert').each(function() {
        $(this).fadeOut(1500);
    });
}

$('#hide-deli-check').change(function(){
    let c = $(this).is(":checked");
    if (c == true) {
        $('tr').each(function(){
            let depts = $(this).find('td.super-depts').text();
            //if (depts.includes('DELI')) {
            if (depts.indexOf('DELI') != -1) {
                $(this).hide();
            }
        });
    } else {
        $('tr').each(function(){
            let depts = $(this).find('td.super-depts').text();
            console.log(depts);
            if (depts.includes('DELI')) {
                $(this).show();
            }
        });

    }
    indexCheckboxes();
});

$('#hide-wait-check').change(function(){
    let c = $(this).is(":checked");
    if (c == true) {
        $('tr').each(function(){
            let comments = $(this).find('td:eq(7)').text();
            console.log(comments);
            if (comments.indexOf('WAIT') != -1) {
                $(this).hide();
            }
        });
    } else {
        $('tr').each(function(){
            let comments = $(this).find('td:eq(7)').text();
            console.log(comments);
            if (comments.indexOf('WAIT') != -1) {
                $(this).show();
            }
        });

    }
    indexCheckboxes();
});

$('#show-deli-check').change(function(){
    let c = $(this).is(":checked");
    if (c == true) {
        $('tr').each(function(){
            let depts = $(this).find('td.super-depts').text();
            if (!depts.includes('DELI') && !$(this).hasClass("thead")) {
                $(this).hide();
            }
        });
    } else {
        $('tr').each(function(){
            let depts = $(this).find('td.super-depts').text();
            if (!depts.includes('DELI')) {
                $(this).show();
            }
        });

    }
    indexCheckboxes();
});
var showDiscrFound = $('.showDiscrFound').click(function(){
    $('#discrFound').text('');
    let text = $(this).attr('title');
    $('#discrFound').append("<div>Item(s) found in multiple batches:</div>");
    $('#discrFound').append(text);
});
JAVASCRIPT;

    }

    public function css_content()
    {
        return <<<HTML
span.supertab {
    padding: 2px;
    margin: 1px;
    cursor: default;
    font-weight: bold;
    text-shadow: 1px 1px lightgrey;
}
button:focus {
    color: lightblue;
}
.panel-default {
    //border: none;
}
table.alert-info,
table.alert-primary,
table.alert-success {
    background: #e0e0e0;
}
textarea { resize: vertical }
.input-addon-btn {
    width: 100%;
    height: 100%;
    border: none;
}
.vertical-alignment-helper {
    display:table;
    height: 100%;
    width: 100%;
    pointer-events:none; /* This makes sure that we can still click outside of the modal to close it */
}
.vertical-align-center {
    /* To center vertically */
    display: table-cell;
    vertical-align: middle;
    pointer-events:none;
}
.input-content {
    /* Bootstrap sets the size of the modal in the modal-dialog class, we need to inherit it */
    width:inherit;
    height:inherit;
    /* To center horizontally */
    margin: 0 auto;
    pointer-events: all;
    width: 600px;
    height: 150px;
}
#alert {
    position: relative;
}
#resp {
    position: absolute;
    top: -45px;
    right: 10px;
}
.batchLogInput {
    border: 1px transparent;
    background-color: transparent;
    width: 100%;
}
.btn-wide {
    width: 100%;
    margin-top: 3px;
}
.batchTable {
    border: 2px transparent;
    border-radius: 0;
}
span.panel-header {
    font-weight: bold;
    //color: darkblue;
}
div.main {
    max-width: 600px;
    text-align: left;
    padding:15px;
}
#checkAll {
    border: 5px solid blue;
    background-color: red;
    padding: 55px;
}
.divider {
    background-color: lightgrey;
    height: 2px;
    border-radius: 2px;
    margin-bottom: 10px;
}
h4 {
    font-weight: bold   font-weight: bold;;
}
HTML;
    }

    public function helpContent()
    {
        return <<<HTML
        <h4>Product Review</h4>
        <p>Mark a product as reviewed once the following
            information has been verified as current:
            <ul>
                <li>Cost</li>
                <li>Sku</li>
                <li>Default Vendor</li>
            </ul>
        </p>
        <h4>Vendor Review Schedule</h4>
        <p>Lists active vendors (excluding vendors
            updated every month) in order of the number
            of products that have been reviewed within
            the given timeframe.
        </p>
        <h4>Batch Review Log</h4>
        <p>Is a record of price change batches. Batches are
            uploaded to this page manually by auditor.
            <ul>
                <li><b>Print</b> mark one batch as printed / open Signs From Search
                    to print tags/signs.</li>
                <li><b>Print All</b> mark all batches currently in the "Un-Forced Batches"
                    table as printed / open Signs From Search to print tags/signs.</li>
                <li><b>Force</b> force a batch in POS and mark it as forced.</li>
            </ul>
        </p>
        <h4>Rolling Price Changes</h4>
        <p>Enter a date range to pull up a list of items in the Vendor Pricing
            Batch page from vendors who had products in price change batches
            that were forced within the span of time requested.</p>
HTML;
    }

    public function unitTest($phpunit)
    {
        $phpunit->assertInternalType('string', $this->css_content());
        $phpunit->assertInternalType('string', $this->javascript_content());
        $phpunit->assertInternalType('string', $this->get_view());
        $phpunit->list = "4011\r\n111";
        $phpunit->assertInternalType('string', $this->get_list_view());
        $phpunit->upc = '4011';
        $phpunit->assertInternalType('string', $this->get_upc_view());
        $phpunit->vendor = 1;
        $phpunit->assertInternalType('string', $this->get_vendor_view());
        $phpunit->assertInternalType('string', $this->get_schedule_setup_view());
    }
}

FannieDispatch::conditionalExec();