CORE-POS/IS4C

View on GitHub
fannie/reports/SalesToday/SalesTodayReport2.php

Summary

Maintainability
D
2 days
Test Coverage
F
8%
<?php
/*******************************************************************************

    Copyright 2009 Whole Foods 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

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

/* --FUNCTIONALITY- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Show total sales by hour for today from dlog.
 * Offer dropdown of superdepartments and, on-select, display the same report for
 *  that superdept only.
 * This page extends FanniePage because it is simpler than most reports
 *  and would be encumbered by the FannieReportPage structure.
*/

use COREPOS\Fannie\API\data\DataCache;
use COREPOS\Fannie\API\lib\Store;

include(dirname(__FILE__) . '/../../config.php');
include_once(__DIR__ . '/../../classlib2.0/FannieAPI.php');

class SalesTodayReport2 extends \COREPOS\Fannie\API\FannieReportTool 
{
    public $description = '[Today\'s Sales] shows current day totals by hour.';
    public $report_set = 'Sales Reports';

    protected $selected = -1;
    protected $store = 0;
    protected $name = "";
    protected $supers = array();

    public function preprocess()
    {
        $dbc = $this->connection;
        $dbc->selectDB($this->config->get('OP_DB'));
        $this->form = new COREPOS\common\mvc\FormValueContainer();
        try {
            $this->store = $this->form->store;
        } catch (Exception $ex) { 
            $this->store = Store::getIdByIp();
        }


        $this->title = "Fannie : Today's Sales";
        $this->header = '';

        $this->addScript($this->config->get('URL').'src/javascript/Chart.min.js');
        $this->addScript('stChart.js?date=20171121');

        return true;

    // preprocess()
    }

    public function body_content()
    {
        $dbc = $this->connection;
        $dbc->selectDB($this->config->get('OP_DB'));
        $transDB = $this->config->get('TRANS_DB') . $dbc->sep();
        $nabs = DTrans::memTypeIgnore($dbc);

        // hourly sales today
        $query = "
            SELECT SUM(total) AS ttl,
                ". $dbc->hour('tdate') . " AS hr
            FROM {$transDB}dlog AS d
                LEFT JOIN MasterSuperDepts AS t ON d.department = t.dept_ID
            WHERE t.superID > 0 
                AND " . DTrans::isStoreID($this->store, 'd') . "
                AND d.trans_type IN ('I','D','M')
                AND d.memType NOT IN {$nabs}
            GROUP BY " . $dbc->hour('tdate') . "
            ORDER BY " . $dbc->hour('tdate');
        $prep = $dbc->prepare($query);
        $res = $dbc->execute($prep, array($this->store));
        $today = array();
        while ($row = $dbc->fetchRow($res)) {
            $today[] = $row;
        }

        $cache = DataCache::check('SameWeekdaySales');
        if (!is_array($cache)) {
            $cache = array();
        }
        if (isset($cache[$this->store])) {
            $avg = $cache[$this->store]['avg'];
            $lastWeek = $cache[$this->store]['lastweek'];
        } else {
            $query = "
                SELECT SUM(total) AS ttl,
                    ". $dbc->hour('tdate') . " AS hr
                FROM {$transDB}dlog_90_view AS d
                    LEFT JOIN MasterSuperDepts AS t ON d.department = t.dept_ID
                WHERE t.superID > 0 
                    AND " . DTrans::isStoreID($this->store, 'd') . "
                    AND d.trans_type IN ('I','D','M')
                    AND d.tdate BETWEEN ? AND ?
                    AND d.memType NOT IN {$nabs}
                GROUP BY " . $dbc->hour('tdate') . "
                ORDER BY " . $dbc->hour('tdate');
            $prep = $dbc->prepare($query);
            $lastWeek = array();
            $avg = array();
            for ($i=1; $i<=5; $i++) {
                $date = date('Y-m-d', strtotime($i*7 . ' days ago'));
                $res = $dbc->execute($prep, array($this->store, $date . ' 00:00:00', $date . ' 23:59:59'));
                while ($row = $dbc->fetchRow($res)) {
                    if ($i == 1) {
                        $lastWeek[] = array('hr' => $row['hr'], 'ttl' => $row['ttl']);
                    }
                    if (!isset($avg[$row['hr']])) {
                        $avg[$row['hr']] = array('hr' => $row['hr'], 'ttl'=>0);
                    }
                    $avg[$row['hr']]['ttl'] += $row['ttl'];
                }
            }
            $avg = array_map(function ($i) { return array('hr'=>$i['hr'], 'ttl'=>$i['ttl']/5); }, array_values($avg));
            $cache[$this->store] = array('avg'=>$avg, 'lastweek'=>$lastWeek);
            DataCache::freshen($cache, 'day', 'SameWeekdaySales');
        }
        include(__DIR__ . '/feed.php');
        $feedCache = '/tmp/feed.ics';
        if (!file_exists($feedCache) || (time() - filemtime($feedCache)) > (60*60)) {
            $fp = fopen($feedCache, 'w');
            $ch = curl_init($feed);
            curl_setopt($ch, CURLOPT_FILE, $fp);
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            $success = curl_exec($ch);
            curl_close($ch);
            fclose($fp);
        }
        $cal = '';
        try {
            $fp = fopen($feedCache, 'r');
            $document = Sabre\VObject\Reader::read($fp, Sabre\VObject\Reader::OPTION_FORGIVING);
            $events = $document->getBaseComponents('VEvent');
            $todayDT = new DateTime(date('Y-m-d'));
            $counter = 0;
            foreach ($events as $event) {
                $start = $event->DTSTART->getDateTime();
                if ($start < $todayDT) continue;
                $end = $event->DTEND->getDateTime();

                $startDay = $start->format('D M jS');
                $startTime = $start->format('g:ia');
                $endDay = $end->format('D M jS');
                $endTime = $end->format('g:ia');

                $highlight = '';
                if ($startDay == $todayDT->format('D M jS')) {
                    $highlight = 'class="alert-info"';
                }

                $cal .= '<p ' . $highlight . '>';
                $event->SUMMARY = str_replace('Copy: ', '', $event->SUMMARY);
                $cal .= '<strong>' . $event->SUMMARY . '</strong><br />';

                if ($startDay == $endDay) {
                    $cal .= $startDay . ' ' . $startTime . ' - ' . $endTime . '<br />';
                } else {
                    $cal .= $startDay . ' ' . $startTime . ' - ' . $endDay . ' ' . $endTime . '<br />';
                }
                if ($event->LOCATION) {
                    $cal .= 'Location: ' . $event->LOCATION . '<br />';
                }
                if ($event->DESCRIPTION) {
                    //$cal .= nl2br(trim($event->DESCRIPTION)) . '<br />';
                }
                $cal .= '</p>';

                $counter++;
                if ($counter >= 3) break;
            }
        } catch (Exception $ex) {
            // calendar was unavailable
        }

        ob_start();
        echo '<div class="row">';
        echo '<div class="col-sm-6">';
        echo "<div class=\"text-center \"><h1>Today's <span style=\"color:green;\">$this->name</span> Sales!</h1>";
        echo "<table class=\"table table-bordered no-bs-table\">"; 
        echo "<tr><td><b>Hour</b></td><td><b>Sales</b></td></tr>";
        $sum = 0;
        foreach ($today as $row) {
            printf("<tr class=\"datarow\"><td class=\"x-data\">%d</td><td class=\"y-data text-right\">%.2f</td></tr>",
                $row[1], $row[0]);
            $sum += $row[0];
        }
        echo "<tr><th width=60px class='text-left'>Total</th><td class='text-right'>";
        echo number_format($sum,2);
        echo "</td></tr></table>";

        $stores = FormLib::storePicker();
        echo '<div class="form-group form-inline">For: '
            . $stores['html'] . 
            '</div>';
        echo '</div>';
        echo '</div>';
        echo '<div class="col-sm-5">';
        if ($cal) {
            $cal = '<h2>Upcoming Events</h2>' . $cal;
        }
        //echo $cal;
        echo '</div>';
        echo '</div>';

        echo '<div id="chartDiv"><canvas id="chartCanvas"></canvas></div>';

        $mapper = function($i) { return array('x'=>(int)$i['hr'], 'y'=>$i['ttl']); };
        $filter = function ($i) { return $i['x'] >= 7; };
        $points = array(
            'avg' => array_map($mapper, $avg),
            'today' => array_map($mapper, $today),
            'lastWeek' => array_map($mapper, $lastWeek),
        );
        $points['avg'] = array_values(array_filter($points['avg'], $filter));
        $points['today'] = array_values(array_filter($points['today'], $filter));
        $points['lastWeek'] = array_values(array_filter($points['lastWeek'], $filter));
        $labels = json_encode(array_map(function ($i) { return $i['x']; }, $points['avg']));
        $points = json_encode($points);
        $dayName = json_encode(date('D'));
        $this->addOnloadCommand("stChart.lineChart('chartCanvas', {$labels}, {$points}, {$dayName});");
        $this->addOnloadCommand("\$('select[name=store]').change(function() { location='?store='+this.value; });");

        echo '</div>';

        return ob_get_clean();
    // body_content()
    }

    public function css_content()
    {
        return <<<CSS
.no-bs-table {
    width: auto !important;
    margin-left: auto;
    margin-right: auto;
}
CSS;
    }

    public function helpContent()
    {
        return '<p>Hourly Sales for the current day. The drop down menu
            can switch the report to a single super department.</p>';
    }

// SalesTodayReport
}

FannieDispatch::conditionalExec();