Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 183
0.00% covered (danger)
0.00%
0 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
StoreController
0.00% covered (danger)
0.00%
0 / 183
0.00% covered (danger)
0.00%
0 / 13
2070
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 checkSalesDayHash
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
30
 getFiveStarsSettings
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 insertSalesDayHash
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 receiveSalesData
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
56
 getPointsForDay
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 getPostsForDay
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
12
 postPointsToFiveStarsAPI
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 getMemberInfoFromFiveStarsAPI
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 formatMemberInfo
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
 createReportVarsByRow
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 1
90
 money_format
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getPointsReportByDateRange
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3namespace BuyerKiosk\FiveStars\Controllers;
4
5
6use BuyerKiosk\FiveStars\API;
7use BuyerKiosk\FiveStars\Points;
8use BuyerKiosk\FiveStars\Sale;
9class StoreController extends BaseController {
10
11    public function __construct($app, \Store $store) {
12        parent::__construct($app, $store);
13    }
14    public function checkSalesDayHash($hash, $date) {
15        $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
16        $this->db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
17        $stmt = $this->db->prepare("SELECT hash FROM salesPostHash WHERE typeNum = :typeNum AND date = :date");
18        $stmt->bindValue(":date", $date);
19        $stmt->bindValue(":typeNum", $this->store->getTypeNum());
20        if($stmt->execute()) {
21            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
22            if($row && isset($row['hash']) && $row['hash'] == $hash) {
23                return true;
24            }
25        } else {
26            $this->log->LogError("Error Checking Day's Hash: ".(String)$this->db->errorInfo());
27        }
28
29        return false;
30    }
31    public function getFiveStarsSettings() {
32        return array(
33            'softwareID' => $this->store->getFiveStarsSoftwareID(),
34            'storeID' => $this->store->getFiveStarsStoreID(),
35            'taxIncluded' => $this->store->getFiveStarsTaxIncluded(),
36            'buysIncluded' => $this->store->getFiveStarsBuysIncluded()
37        );
38    }
39    public function insertSalesDayHash($hash, $date) {
40        $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
41        $this->db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
42        $stmt = $this->db->prepare("INSERT INTO salesPostHash (hash, date, typeNum) VALUES (:hash, :date, :typeNum)");
43        $stmt->bindValue(":hash", $hash);
44        $stmt->bindValue(":date", $date);
45        $stmt->bindValue(":typeNum", $this->store->getTypeNum());
46        if($stmt->execute()) {
47            return true;
48        } else {
49            $this->log->LogError("Error Inserting Day's Hash: ".(String)$this->db->errorInfo());
50        }
51        return false;
52    }
53
54    public function receiveSalesData($json, $date = null)
55    {
56        if($date == NULL) {
57            $date = new \DateTime("now", new \DateTimeZone($this->store->getTimeZone()));
58        } else {
59            $date = new \DateTime($date, new \DateTimeZone($this->store->getTimeZone()));
60        }
61        $this->log->LogDebug("Date Set: ".$date->format("Y-m-d"));
62        $data = json_decode($json);
63        $errorCount = 0;
64        $insertCount = 0;
65        $noPhoneCount = 0;
66        if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
67            $this->log->LogError("Error Decoding JSON from Store [" . $this->store->getTypeNum() . "]");
68            return false;
69        }
70        $this->storeDB = dbConnectByName($this->store->getDbName());
71        foreach ($data as $saleRecord) {
72            if($saleRecord->phoneNum !== "9999999999") {
73                $sale = new Sale($this->store, $this->storeDB);
74                $sale->salesAmount = $saleRecord->salesAmount;
75                $sale->buyAmount = $saleRecord->buyAmount;
76                $sale->taxAmount = $saleRecord->taxAmount;
77                $sale->phone = $saleRecord->phoneNum;
78                $sale->transID = $saleRecord->transID;
79                $sale->employee = $saleRecord->employee;
80                if ($sale->insert($date)) {
81                    $this->log->LogError("Successful Insert of Phone: [".$saleRecord->phoneNum."] and transID: [".$saleRecord->transID."]");
82                    $insertCount++;
83                } else {
84                    $this->log->LogError("Error on Phone: [".$saleRecord->phoneNum."] and transID: [".$saleRecord->transID."]");
85                    $errorCount++;
86                }
87            } else {
88                $this->log->LogError("No phone sent: [".$saleRecord->phoneNum."] and transID: [".$saleRecord->transID."]");
89                $noPhoneCount++;
90            }
91
92        }
93        $this->getPointsForDay($date->format('Y-m-d'));
94        $this->getPostsForDay($date->format('Y-m-d'));
95        return array("insertCount"=>$insertCount, "errorCount"=>$errorCount, "noPhoneCount"=>$noPhoneCount, "date" => $date->format('Y-m-d'));
96    }
97    public function getPointsForDay($date) {
98        try {
99            $stmt = $this->storeDB->prepare("SELECT phoneNum,SUM(salesAmount) as totalSales,SUM(taxAmount) as totalTax, SUM(buyAmount) as totalBuy FROM dailySalesData WHERE date = :date GROUP BY phoneNum");
100            $stmt->bindValue(":date", $date);
101            $stmt->execute();
102            while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
103                $points = new Points($this->store, $this->storeDB);
104                $points->totalBuys = $row['totalBuy'];
105                $points->totalSales = $row['totalSales'];
106                $points->totalTax = $row['totalTax'];
107                $points->phone = $row['phoneNum'];
108                $points->date = $date;
109                $points->calculatePoints();
110                $this->log->LogDebug("Points Calculated: ".$points->getPoints());
111                $points->insert();
112            }
113        } catch (\PDOException $e) {
114            $this->log->LogError($e->getMessage());
115        }
116    }
117    public function getPostsForDay($date) {
118        global $db_name;
119        $db = dbConnectByName($db_name);
120        $this->log->LogDebug("Posts Date: ".$date);
121        try {
122            $stmt = $this->storeDB->prepare("SELECT id, phone, points FROM fiveStarsPoints WHERE points != 0 AND date = :date");
123            $stmt->bindValue(":date", $date);
124            $stmt->execute();
125            $data = $stmt->fetchAll(\PDO::FETCH_ASSOC);
126            $this->log->LogDebug("Data Count: ".count($data));
127            foreach ($data as $record) {
128                $this->log->LogDebug("Insert for ".$record['phone']);
129                $query = $db->prepare("INSERT INTO fsOutgoing (typeNum, phone, points, localID, dateAdded, softwareID) VALUES (:typeNum, :phone, :points, :localID, CURRENT_TIMESTAMP, :softwareID)");
130                $query->bindValue(":typeNum", $this->store->getTypeNum());
131                $query->bindValue(":phone", $record['phone']);
132                $query->bindValue(":points", $record['points']);
133                $query->bindValue(":localID", $record['id']);
134                $query->bindValue(":softwareID", $this->store->getFiveStarsSoftwareID());
135                $query->execute();
136            }
137        } catch (\PDOException $e) {
138            $this->log->LogError($e->getMessage());
139        }
140    }
141    private function postPointsToFiveStarsAPI(Points $points) {
142        $endpoint = $this->endpointBase."/sales/";
143        $data = array("phone" => $points->phone, "points" => array("amount" => $points->getPoints()), "checking" => "partner");
144        $api = new API();
145        $result = $api->api_call($endpoint, $data);
146        $this->log->LogDebug(json_encode($result));
147    }
148    public function getMemberInfoFromFiveStarsAPI($phone) {
149        global $fiveStarsAPIURL;
150        $fiveStarsSoftwareID = $this->store->getFiveStarsSoftwareID();
151        $fiveStarsAPI = new API();
152        $phone = $fiveStarsAPI->phone_hash($phone);
153        $endpoint = "/businesses/".$fiveStarsSoftwareID."/memberships/by-phone/".$phone;
154        $result = $fiveStarsAPI->api_call($endpoint);
155        return $this->formatMemberInfo($result);
156    }
157    private function formatMemberInfo($result) {
158        if(isset($result['account']['phone'])) {
159            if($result['account']['name'] == "") {
160                $result['account']['name'] = "Unknown";
161            }
162            if($result['account']['email'] == "") {
163                $result['account']['email'] = "Unknown";
164            }
165            if($result['account']['birthday'] == "") {
166                $result['account']['birthday'] = "Unknown";
167            }
168            $result['account']['phoneFormatted'] = formatPhoneNumber($result['account']['phone']);
169            return $result;
170        }
171        return $result;
172    }
173
174    public function createReportVarsByRow($row)
175    {
176        setlocale(LC_MONETARY, 'en_US');
177        $results = [];
178        $results['date'] = $row['date'];
179        $dateSort = new \DateTime($row['date']);
180        $results['dateSort'] = $dateSort->format("U");
181        $results['id'] = $row['id'];
182        $results['phone'] = formatPhoneNumber($row['phone']);
183        $results['phoneUnformatted'] = $row['phone'];
184        $results['fullName'] = $row['firstName'] . " " . $row['lastName'];
185        $results['points'] = $row['points'];
186        $results['totalSales'] = $this->money_format($row['totalSales']);
187        $results['totalBuys'] = $this->money_format($row['totalBuys']);
188        $results['totalTax'] = $this->money_format($row['totalTax']);
189        $results['pointsRedeemed'] = $row['pointsRedeemed'];
190        if ((int)$results['points'] > 0) {
191            $results['class'] = 'green';
192        } else {
193            $results['class'] = 'return';
194        }
195        if($row['completedAt'] == 'Other') {
196            $results['completed'] = "Error";
197            $results['class'] = "danger";
198        } else if($row['completedAt'] == NULL && $row['points'] > 0) {
199            $results['completed'] = "Pending";
200            $results['class'] = "info";
201            $results['completedAtFormatted'] = "Pending";
202        } else if((int)$row['totalBuys'] > 0 && (int)$row['points'] == 0) {
203            $results['class'] = "info";
204            $results['completed'] = "Pending";
205            if($this->store->getFiveStarsBuysIncluded()) {
206                $results['completedAtFormatted'] = "Pending";
207            } else {
208                $results['completedAtFormatted'] = "Ignored Buy";
209            }
210        } else {
211            //$this->log->LogDebug("Completed Timestamp: ".$row['completedAt']);
212            $dateTime = new \DateTime();
213            $dateTime->setTimestamp($row['completedAt']);
214            $dateTime->setTimezone(new \DateTimeZone($this->store->getTimeZone()));
215            $results['completedAtFormatted'] = $dateTime->format('Y-m-d g:i A');
216        }
217
218        if((int)$row['pointsRedeemed'] > 0) {
219            $results['points'] = $results['pointsRedeemed'];
220            $results['class'] = 'redemption';
221            $results['completedAtFormatted'] = "Redeemed";
222        }
223        return $results;
224    }
225    private function money_format($number) {
226        if($number > 0) {
227            return '$' . number_format($number, 2);
228        }
229        return "-";
230    }
231
232    public function getPointsReportByDateRange($dateStart, $dateEnd, $showBuys) {
233        $surveyArray = [];
234        $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
235        $this->db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
236        $buysString = "AND (totalSales != 0 OR totalBuys != 0 OR pointsRedeemed != 0 OR totalReturns != 0)";
237        if($showBuys == 0) {
238            $buysString = "AND ((totalBuys = 0.00 AND totalSales != 0) OR pointsRedeemed != 0)";
239        }
240        $storeDB = $this->store->getDbName();
241        try{
242            $stmt = $this->db->prepare("SELECT
243                                                ".$storeDB.".fiveStarsPoints.id,
244                                                date,
245                                                ".$storeDB.".fiveStarsPoints.phone,
246                                                totalSales,
247                                                totalBuys,
248                                                totalTax,
249                                                pointsRedeemed,
250                                                totalReturns,
251                                                kiosk_buykiosk.fsOutgoing.points,
252                                                kiosk_buykiosk.fsOutgoing.posted,
253                                                kiosk_buykiosk.fsOutgoing.queued,
254                                                kiosk_buykiosk.fsOutgoing.completedAt                                  
255                                            FROM
256                                                ".$storeDB.".fiveStarsPoints
257                                                LEFT OUTER JOIN kiosk_buykiosk.fsOutgoing ON kiosk_buykiosk.fsOutgoing.localID =  ".$storeDB.".fiveStarsPoints.id 
258                                            WHERE
259                                                date BETWEEN :start
260                                                AND :end
261                                                ".$buysString."                                                                                                 
262                                            ORDER BY ".$storeDB.".fiveStarsPoints.id DESC");
263            $stmt->bindValue(":start", $dateStart);
264            $stmt->bindValue(":end", $dateEnd);
265            if($stmt->execute()) {
266                while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
267                    $surveyArray[] = $this->createReportVarsByRow($row);
268
269                }
270                return $surveyArray;
271            } else {
272                $this->log->LogDebug("Can't Execute The Points Report Query");
273                return null;
274            }
275        } catch (\PDOException $e) {
276            $this->log->LogDebug("PDO Exception Found");
277            $this->log->LogError($e->getMessage());
278            return null;
279        }
280    }
281}