Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 196
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
SimpleQueue
0.00% covered (danger)
0.00%
0 / 196
0.00% covered (danger)
0.00%
0 / 10
4290
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 readDB
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
56
 findInDatabase
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
 ingestData
0.00% covered (danger)
0.00%
0 / 87
0.00% covered (danger)
0.00%
0 / 1
1260
 queueItemBuilder
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
42
 updateDatabase
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 addToDatabase
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 getActiveQueueItems
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getCompletedQueueItems
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 getAblyArray
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace BuyerKiosk\SimpleQueue;
4
5class SimpleQueue
6{
7    private $queue;
8    private $activeIDArray;
9    private $channel;
10    private $store;
11    private $log;
12    public function __construct($store)
13    {
14        $this->store = $store;
15        $this->log = new \KLogger($_ENV['LOG_DIR']."/simpleQueue.log", \KLogger::DEBUG);
16        $this->ably = new \Ably\AblyRest($_ENV['ABLY_KEY']);
17        $this->channel = $this->ably->channels->get($store->getTypeNum());
18    }
19
20    private function readDB()
21    {
22        $db = dbConnectByName($this->store->getDBName());
23        if ($db === null) {
24            throw new \Exception('Database connection failed');
25        }
26
27        $tempQueueArray = [];
28        $tempQueueArray['active'] = [];
29        $tempQueueArray['completed'] = [];
30        $stmt = $db->query("SELECT * FROM simpleQueue WHERE status IN(0,1) ORDER BY timeEntered DESC");
31        if ($stmt === false) {
32            throw new \Exception('Database query failed');
33        }
34
35        while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
36            if (empty($row)) {
37                return $tempQueueArray;
38            } else {
39                if ($row['status'] == 0) {
40                    $this->activeIDArray[] = $row['transID'];
41                    $tempQueueArray['active'][] = new SimpleQueueItem($row['transID'], $row['firstName'], $row['lastName'], $row['status'], $row['timeEntered'], $row['timeCompleted']);
42                } elseif ($row['status'] == 1) {
43                    $this->activeIDArray[] = $row['transID'];
44                    $tempQueueArray['completed'][] = new SimpleQueueItem($row['transID'], $row['firstName'], $row['lastName'], $row['status'], $row['timeEntered'], $row['timeCompleted']);
45                }
46            }
47        }
48
49        return $tempQueueArray;
50    }
51    private function findInDatabase($transID) {
52        $db = dbConnectByName($this->store->getDBName());
53        if ($db === null) {
54            throw new \Exception('Database connection failed');
55        }
56        try {
57            $stmt = $db->prepare("SELECT * FROM simpleQueue WHERE transID = :transID");
58            $stmt->bindParam(':transID', $transID);
59            $stmt->execute();
60            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
61            return !empty($row);
62        } catch (\PDOException $e) {
63            $this->log->LogError($e->getMessage());
64            return false;
65        }
66    }
67
68    public function ingestData($data) {
69        if (!isset($this->queue)) {
70            $this->queue = $this->readDB();
71        }
72        if ($this->queue === null) {
73            $tempQueueArray = [];
74            $tempQueueArray['active'] = [];
75            $tempQueueArray['completed'] = [];
76        }
77        $this->log->LogDebug("Queue: ".print_r($this->queue, true));
78        $activeQueue = $this->queue['active'];
79        $completedQueue = $this->queue['completed'];
80        $this->log->LogDebug("Active Queue: ".print_r($activeQueue, true));
81        $this->log->LogDebug("Data: ".print_r($data, true));
82
83        foreach($data as $item) {
84            $this->log->LogDebug("Ingesting: ".$item['transID']);
85            $tempQueueItem = $this->queueItemBuilder($item);
86            $foundInActive = false;
87            $this->log->LogDebug("Item Trans ID: ".$tempQueueItem->transID);
88            if (!empty($activeQueue)) {// Compare the data received with the data in the database
89                foreach ($activeQueue as $queueItem) {
90                    if ($queueItem->transID == $tempQueueItem->transID) {
91                        // Ignore any items that have the same status as what's already in the database
92                        if ($queueItem->status == $tempQueueItem->status) {
93                            $foundInActive = true;
94                            continue 2;
95                        }
96                        // If the status has changed, update the database
97                        if ($queueItem->status != $tempQueueItem->status) {
98                            if($tempQueueItem->status == 1) {
99                                $now = getCurrentDateRange();
100                                $tempQueueItem->timeCompleted = $now['dateStart']->format("Y-m-d H:i:s");
101                                $action = "processBuy";
102                            } else if($tempQueueItem->status == 2 && $tempQueueItem->timeCompleted == null) {
103                                $now = getCurrentDateRange();
104                                $tempQueueItem->timeCompleted = $now['dateStart']->format("Y-m-d H:i:s");
105                                $action = "checkOut";
106                            } else if($tempQueueItem->status == 0) {
107                                $action = "addNewBuy";
108                            } else {
109                                $action = "deleteBuy";
110                            }
111                            if (!$this->updateDatabase($tempQueueItem)) {
112                                $this->log->LogError("Failed to update database for item: " . $tempQueueItem->transID);
113                            } else {
114                                $ablyArray = $this->getAblyArray($tempQueueItem, $action);
115                                $this->channel->publish($action, $ablyArray);
116                            }
117                            $foundInActive = true;
118                            continue 2;
119                        }
120                    }
121                }
122            }
123            $this->log->LogDebug("Found in active: ".(int)$foundInActive);
124            // If the item is not found in the active queue, check the rest of the database
125            if(!$foundInActive) {
126                // If the item is found in the database, update it
127                if ($this->findInDatabase($tempQueueItem->transID)) {
128                    $this->log->LogDebug("Status: ".$tempQueueItem->status);
129                    if($tempQueueItem->status == 1) {
130                        $action = "processBuy";
131                    } else if($tempQueueItem->status == 2 && $tempQueueItem->timeCompleted == null) {
132                        $now = getCurrentDateRange();
133                        $tempQueueItem->timeCompleted = $now['dateStart']->format("Y-m-d H:i:s");
134                        $action = "checkOut";
135                    } else if($tempQueueItem->status == 0) {
136                        $action = "addNewBuy";
137                    } else {
138                        $action = "None";
139                    }
140                    if (!$this->updateDatabase($tempQueueItem)) {
141                        $this->log->LogError("Failed to update database for item: " . $tempQueueItem->transID);
142                    } else {
143                        $ablyArray = $this->getAblyArray($tempQueueItem, $action);
144                        if($action != "None")
145                            $this->channel->publish($action, $ablyArray);
146                    }
147                // If the item is not found in the database, add it
148                } else if ($tempQueueItem->status <= 1) {
149                    if($tempQueueItem->status == 1) {
150                        $now = getCurrentDateRange();
151                        $tempQueueItem->timeCompleted = $now['dateStart']->format("Y-m-d H:i:s");
152                    }
153                    if (!$this->addToDatabase($tempQueueItem)) {
154                        $this->log->LogError("Failed to add item to database: " . $tempQueueItem->transID);
155                    } else {
156                        $ablyArray = $this->getAblyArray($tempQueueItem, "addNewBuy");
157                        $this->channel->publish("addNewBuy", $ablyArray);
158                    }
159                }
160            }
161
162        }
163
164
165        // If there is a row in the database with a status of 1 or 0 and it's not in the $data array, update the status to 2
166        if (!empty($activeQueue)) {
167            $this->log->LogDebug("Active Queue: " . print_r($activeQueue, true));
168            foreach ($activeQueue as $queueItem) {
169                $this->log->LogDebug("Active Queue Item: " . print_r($queueItem, true));
170                if ($queueItem->status <= 1 && !in_array($queueItem->transID, array_column($data, 'transID'))) {
171                    $this->log->LogDebug("Updating: " . $queueItem->transID);
172                    $queueItem->status = 2;
173                    if (!$this->updateDatabase($queueItem)) {
174                        $this->log->LogError("Failed to update database for item: " . $queueItem->transID);
175                    } else {
176                        $ablyArray = $this->getAblyArray($queueItem, "checkOut");
177                        $this->channel->publish("checkOut", $ablyArray);
178
179                    }
180                }
181            }
182        }
183        // If there is a row in the database with a status of 1 or 0 and it's not in the $data array, update the status to 2
184        if(!empty($completedQueue)) {
185            foreach ($completedQueue as $queueItem) {
186                $this->log->LogDebug("Active Queue Item: ".print_r($queueItem, true));
187                if ($queueItem->status <= 1 && !in_array($queueItem->transID, array_column($data, 'transID'))) {
188                    $this->log->LogDebug("Updating: ".$queueItem->transID);
189                    $queueItem->status = 2;
190                    if (!$this->updateDatabase($queueItem)) {
191                        $this->log->LogError("Failed to update database for item: " . $queueItem->transID);
192                    } else {
193                        $ablyArray = $this->getAblyArray($queueItem, "checkOut");
194                        $this->channel->publish("checkOut", $ablyArray);
195
196                    }
197                }
198            }
199        }
200    }
201
202    private function queueItemBuilder($item) {
203        $this->log->LogDebug("Queueing: ".$item['transID']);
204        //I need to inspect item['transStatus'] and item['transVoidMode'] to determine the overall item status.
205        //If transStatus = "ACTIVE" and transVoidMode = "" then the item is queued. $status = 0
206        //If transStatus = "ACTIVE" and transVoidMode = "VOIDSAVED" then the item is voided. $status = 3
207        //If transStatus = "QUOTE" and transVoidMode = "" then the item is quoted. $status = 1
208        //If transStatus = "QUOTE" and transVoidMode = "CANCELED" then the item is voided. $status = 3
209
210        $status = 0;
211        $this->log->LogDebug("Processing item: " . $item['transID']);
212        $this->log->LogDebug("transStatus: " . $item['transStatus']);
213        $this->log->LogDebug("transVoidMode: " . $item['transVoidMode']);
214
215        if($item['transStatus'] == "QUOTE") {
216            if($item['transVoidMode'] == "CANCELLED") {
217                $status = 3;
218            } else {
219                $status = 1;
220            }
221        } elseif($item['transStatus'] == "ACTIVE") {
222            if($item['transVoidMode'] == "VOIDSAVED") {
223                $status = 3;
224            } else if($item['transVoidMode'] == "ABORTED") {
225                $status = 3;
226            }
227        }
228
229        $this->log->LogDebug("Resulting status: " . $status);
230        return new SimpleQueueItem($item['transID'], $item['firstName'], $item['lastName'], $status, 1);
231    }
232    private function updateDatabase($queueItem) {
233        $db = dbConnectByName($this->store->getDBName());
234        if ($db === null) {
235            throw new \Exception('Database connection failed');
236        }
237        try {
238            $stmt = $db->prepare("UPDATE simpleQueue SET status = :status, timeCompleted = :timeCompleted WHERE transID = :transID");
239            $stmt->bindParam(':status', $queueItem->status);
240            $stmt->bindParam(':timeCompleted', $queueItem->timeCompleted);
241            $stmt->bindParam(':transID', $queueItem->transID);
242            $stmt->execute();
243            return true;
244        } catch (\PDOException $e) {
245            $this->log->LogError($e->getMessage());
246            return false;
247        }
248    }
249
250    private function addToDatabase($queueItem) {
251        $db = dbConnectByName($this->store->getDBName());
252        if ($db === null) {
253            throw new \Exception('Database connection failed');
254        }
255        try {
256            $stmt = $db->prepare("INSERT INTO simpleQueue (transID, firstName, lastName, status, timeEntered, timeCompleted) VALUES (:transID, :firstName, :lastName, :status, :timeEntered, :timeCompleted)");
257            $stmt->bindParam(':transID', $queueItem->transID);
258            $stmt->bindParam(':firstName', $queueItem->firstName);
259            $stmt->bindParam(':lastName', $queueItem->lastName);
260            $stmt->bindParam(':status', $queueItem->status);
261            $stmt->bindParam(':timeEntered', $queueItem->timeEntered);
262            $stmt->bindParam(':timeCompleted', $queueItem->timeCompleted);
263            $stmt->execute();
264            return true;
265        } catch (\PDOException $e) {
266            $this->log->LogError($e->getMessage());
267            return false;
268        }
269    }
270
271    public function getActiveQueueItems() {
272        if (!isset($this->queue)) {
273            $this->queue = $this->readDB();
274        }
275        $this->log->LogDebug("Active Queue: ".print_r($this->queue['active'], true));
276        return $this->queue['active'];
277    }
278    public function getCompletedQueueItems() {
279        $this->log->LogDebug("Getting completed queue items");
280        if (!isset($this->queue)) {
281            $this->queue = $this->readDB();
282        }
283        $this->log->LogDebug("Completed Queue: ".print_r($this->queue['completed'], true));
284        return $this->queue['completed'];
285    }
286    private function getAblyArray($queueItem, $action)
287    {
288        if($queueItem->firstName == null) {
289            $queueItem->firstName = "#".$queueItem->transID;
290            $queueItem->lastName = "";
291        }
292        if($queueItem->timeCompleted == null) {
293            $queueItem->timeCompleted = "0000-00-00 00:00:00";
294        }
295        $entryData = array('action' => $action
296        , 'category' => $this->store->getTypeNum()
297        , 'buyID' => $queueItem->transID
298        , 'firstName' => $queueItem->firstName
299        , 'lastName' => $queueItem->lastName
300        , 'timeEntered' => $queueItem->timeEntered
301        , 'timeStarted' => "0000-00-00 00:00:00"
302        , 'timeCompleted' => $queueItem->timeCompleted
303        , 'sortStarted' => "0000-00-00 00:00:00"
304        , 'sortCompleted' => "0000-00-00 00:00:00"
305        , 'buyerID' => NULL
306        , 'numContainers' => 1
307        , 'processedContainers' => 0
308        , 'textMe' => 1
309        , 'inStore' => 1
310        , 'isNewCustomer' => 1
311        );
312        return $entryData;
313    }
314}