Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 195
0.00% covered (danger)
0.00%
0 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
BackstockFactory
0.00% covered (danger)
0.00%
0 / 195
0.00% covered (danger)
0.00%
0 / 16
2162
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
 getLocationsArray
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 prepareLookupArrays
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getAllRecentActions
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getCategoriesArray
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 getBinByID
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 getAllBins
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 findBinByExactName
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 getHiddenBins
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getBinsByLocation
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 getBinsByCategory
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 makeBinReadable
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 1
272
 getStore
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 createReprintJob
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
6
 getReprintJSON
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 bulkCreateBins
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace BuyerKiosk\Backstock;
4
5use Symfony\Component\Validator\Constraints\DateTime;
6
7class BackstockFactory
8{
9    private $store;
10    private $storeDB;
11    private $predis;
12
13    private $locationsArray;
14    private $categoriesArray;
15    private $log;
16
17    public function __construct(\Store $store)
18    {
19        $this->store = $store;
20        $this->storeDB = dbConnectByName($this->store->getDbName());
21        $this->predis = new \Predis\Client($_ENV['REDIS_URL']);
22        $this->log = new \KLogger($_ENV['LOG_DIR']."backstock.log", \KLogger::DEBUG);
23
24    }
25
26    public function getLocationsArray()
27    {
28        $tempArray = [];
29        $stmt = $this->storeDB->prepare("SELECT * FROM bsLocations");
30        $stmt->execute();
31        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
32            $tempArray[$row['id']] = $row;
33            $tempArray[$row['id']]['id'] = $row['id'];
34        }
35        return $tempArray;
36    }
37
38    /**
39     * Prepare lookup arrays for use with makeBinReadable
40     * Call this before using makeBinReadable directly
41     */
42    public function prepareLookupArrays()
43    {
44        $this->locationsArray = $this->getLocationsArray();
45        $this->categoriesArray = $this->getCategoriesArray();
46    }
47
48    public function getAllRecentActions() {
49        $stmt = $this->storeDB->query("SELECT * FROM bsActions WHERE 1 ORDER BY timePerformed DESC, id DESC");
50        $actionsArray = [];
51        while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
52            $tempAction = new Action($this->store);
53            $tempAction->createFromRow($row);
54            $actionsArray[] = $tempAction;
55        }
56        return $actionsArray;
57    }
58
59    public function getCategoriesArray()
60    {
61        $tempArray = [];
62        $stmt = $this->storeDB->prepare("SELECT * FROM bsCategories");
63        $stmt->execute();
64        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
65            $tempArray[$row['id']]['id'] = $row['id'];
66            $tempArray[$row['id']]['name'] = $row['name'];
67            $color = preg_replace('/[^A-Za-z0-9\-]/', '', $row['color']);
68            $tempArray[$row['id']]['color'] = $color;
69        }
70        return $tempArray;
71    }
72
73    public function getBinByID($id)
74    {
75        $bin = new Bin($this->store);
76        if ($bin->readByID($id)) {
77            $this->locationsArray = $this->getLocationsArray();
78            $this->categoriesArray = $this->getCategoriesArray();
79
80            return $this->makeBinReadable($bin);
81        }
82        return null;
83    }
84
85    public function getAllBins($includeHidden = false)
86    {
87        $tempArray = [];
88        if ($includeHidden) {
89            $stmt = $this->storeDB->prepare("SELECT * FROM bsBins WHERE deleted = 0");
90        } else {
91            $stmt = $this->storeDB->prepare("SELECT * FROM bsBins WHERE deleted = 0 AND (active = 1 OR active IS NULL)");
92        }
93        $stmt->execute();
94
95        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
96            $tempBin = new Bin($this->store);
97            $tempBin->readByID($row['id']);
98
99            $this->locationsArray = $this->getLocationsArray();
100            $this->categoriesArray = $this->getCategoriesArray();
101
102            $tempBin = $this->makeBinReadable($tempBin);
103
104            $tempArray[] = $tempBin;
105        }
106        return $tempArray;
107    }
108
109    /**
110     * Search for a bin by exact name match, including hidden bins
111     * Used when scanning a barcode to find a potentially hidden bin
112     *
113     * @param string $name Exact bin name to search for
114     * @return Bin|null The found bin or null
115     */
116    public function findBinByExactName($name)
117    {
118        try {
119            $stmt = $this->storeDB->prepare("SELECT * FROM bsBins WHERE name = :name AND deleted = 0 LIMIT 1");
120            $stmt->bindValue(":name", $name);
121            $stmt->execute();
122
123            $row = $stmt->fetch(\PDO::FETCH_ASSOC);
124            if ($row && $row['id'] > 0) {
125                $tempBin = new Bin($this->store);
126                $tempBin->readByID($row['id']);
127
128                $this->locationsArray = $this->getLocationsArray();
129                $this->categoriesArray = $this->getCategoriesArray();
130
131                return $this->makeBinReadable($tempBin);
132            }
133        } catch (\PDOException $e) {
134            $this->log->LogDebug($e->getMessage());
135        }
136        return null;
137    }
138
139    /**
140     * Get all hidden bins for management/viewing
141     */
142    public function getHiddenBins()
143    {
144        $tempArray = [];
145        $stmt = $this->storeDB->prepare("SELECT * FROM bsBins WHERE deleted = 0 AND active = 0");
146        $stmt->execute();
147
148        $this->locationsArray = $this->getLocationsArray();
149        $this->categoriesArray = $this->getCategoriesArray();
150
151        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
152            $tempBin = new Bin($this->store);
153            $tempBin->readByID($row['id']);
154            $tempBin = $this->makeBinReadable($tempBin);
155            $tempArray[] = $tempBin;
156        }
157        return $tempArray;
158    }
159
160    function getBinsByLocation(Location $location)
161    {
162        $tempArray = [];
163        $stmt = $this->storeDB->prepare("SELECT * FROM bsBins WHERE deleted = 0 AND location = :locationID");
164        $stmt->bindValue(":locationID", $location->id);
165        $stmt->execute();
166        $this->locationsArray = $this->getLocationsArray();
167        $this->categoriesArray = $this->getCategoriesArray();
168        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
169            $tempBin = new Bin($this->store);
170            $tempBin->readByID($row['id']);
171            $tempBin = $this->makeBinReadable($tempBin);
172            $tempArray[] = $tempBin;
173        }
174        return $tempArray;
175
176    }
177    function getBinsByCategory(Category $category) {
178        $tempArray = [];
179        $stmt = $this->storeDB->prepare("SELECT * FROM bsBins WHERE deleted = 0 AND (mainCat = :categoryID OR subCat1 = :categoryID OR subCat2 = :categoryID OR subCat3 = :categoryID)");
180        $stmt->bindValue(":categoryID", $category->id);
181        $stmt->execute();
182        $this->locationsArray = $this->getLocationsArray();
183        $this->categoriesArray = $this->getCategoriesArray();
184        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
185            $tempBin = new Bin($this->store);
186            $tempBin->readByID($row['id']);
187            $tempBin = $this->makeBinReadable($tempBin);
188            $tempArray[] = $tempBin;
189        }
190        return $tempArray;
191    }
192
193    public function makeBinReadable(Bin $tempBin)
194    {
195        //Convert the category IDs into Names we can use
196        if ($tempBin->mainCategory === null || $tempBin->mainCategory === '' || $tempBin->mainCategory === 0) {
197            // Bin has been emptied or never had a category
198            $tempBin->mainCategory = array("name" => "Empty", "color" => "e5e7eb");  // Light gray
199        } elseif (isset($this->categoriesArray[$tempBin->mainCategory])) {
200            $tempBin->mainCategory = $this->categoriesArray[$tempBin->mainCategory];
201        } else {
202            $tempBin->mainCategory = array("name" => "Unknown", "color" => "ffffff");
203        }
204
205
206        $stmt = $this->storeDB->prepare("SELECT * FROM bsActions WHERE binID = :binID  ORDER BY timePerformed DESC, id DESC LIMIT 1");
207        $stmt->bindValue(":binID", $tempBin->id);
208        $stmt->execute();
209        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
210        if($row && $row['id'] > 0) {
211            $action = new Action($this->store);
212            $action->createFromRow($row);
213            switch ($row['action']) {
214                case 0:
215                    $tempBin->actionStringDate = $action->dateReadableShort;
216                    $tempBin->actionStringEmployee = $action->employeeName;
217                    $tempBin->actionStringAction = "Removed Everything";
218                    $tempBin->actionStringCategory ="";
219                    break;
220                case 1:
221                    $tempBin->actionStringDate = $action->dateReadableShort;
222                    $tempBin->actionStringEmployee = $action->employeeName;
223                    $tempBin->actionStringAction = "Added Some ";
224                    $categoryID = (int)$action->categoryID;
225                    $tempBin->actionStringCategory = isset($this->categoriesArray[$categoryID]['name']) ? $this->categoriesArray[$categoryID]['name'] : 'Unknown Category';
226
227                    break;
228                case 2:
229                    $tempBin->actionStringDate = $action->dateReadableShort;
230                    $tempBin->actionStringEmployee = $action->employeeName;
231                    $tempBin->actionStringAction = "Removed Some ";
232                    $categoryID = (int)$action->categoryID;
233                    $tempBin->actionStringCategory = isset($this->categoriesArray[$categoryID]['name']) ? $this->categoriesArray[$categoryID]['name'] : 'Unknown Category';
234                    break;
235                case 3:
236                    $tempBin->actionStringDate = $action->dateReadableShort;
237                    $tempBin->actionStringEmployee = $action->employeeName;
238                    $tempBin->actionStringAction = "Removed Some ";
239                    $categoryID = (int)$action->categoryID;
240                    $tempBin->actionStringCategory = isset($this->categoriesArray[$categoryID]['name']) ? $this->categoriesArray[$categoryID]['name'] : 'Unknown Category';
241                    break;
242            }
243        } else {
244            $tempBin->actionString = "Created On ".$tempBin->dateCreatedReadable;
245        }
246
247        //Convert to the locations IDs into Names we can use
248        $tempBin->locationID = $tempBin->location;
249        if(isset($this->locationsArray) && isset($this->locationsArray[$tempBin->locationID])) {
250            $tempBin->location = $this->locationsArray[$tempBin->locationID]['name'];
251            $tempBin->onSite = $this->locationsArray[$tempBin->locationID]['onsite'];
252        } else {
253            $tempBin->location = "None";
254            $tempBin->onSite = 0;
255        }
256
257
258
259        $date = new \DateTime($tempBin->ageDate, new \DateTimeZone('utc'));
260        $date->setTimezone(new \DateTimeZone($this->store->getTimeZone()));
261        $tempBin->dateCreatedReadable = $date->format("M j, Y");
262        $tempBin->dateCreatedSortable = $date->getTimestamp();
263
264        return $tempBin;
265    }
266
267    /**
268     * @return \Store
269     */
270    public function getStore()
271    {
272        return $this->store;
273    }
274
275    public function createReprintJob($binIDArray) {
276        $data = [];
277        $this->categoriesArray = $this->getCategoriesArray();
278        foreach($binIDArray as $binID) {
279            $tempBin = new Bin($this->store);
280            $tempBin->readByID($binID['id']);
281            $tempBin = $this->makeBinReadable($tempBin);
282            $tempData['date'] = $tempBin->dateCreatedReadable;
283            $tempData['name'] = $tempBin->name;
284            $tempData['mainCat'] = $tempBin->mainCategory['name'];
285            $tempData['uuid'] = $tempBin->uuid;
286            $tempData['quantity'] = $binID['quantity'];
287            $data[] = $tempData;
288        }
289
290        $jobUUID = gen_uuid(8);
291        $this->predis->hset($this->store->getTypeNum(), "reprint_".$jobUUID, json_encode($data));
292        return $jobUUID;
293    }
294
295    public function getReprintJSON($jobUUID) {
296        $return = $this->predis->hget($this->store->getTypeNum(), "reprint_".$jobUUID);
297        $this->predis->hdel($this->store->getTypeNum(), "reprint_".$jobUUID);
298        return $return;
299    }
300
301    public function bulkCreateBins($binPrefix,$binStartingNumber, $binQuantity, $labelQuantity, $locationID) {
302        //$this->locationsArray = $this->getLocationsArray();
303        $binIDArray = [];
304        $this->storeDB->beginTransaction();
305        for($i = 0; $i < $binQuantity; $i++) {
306            $uuid = gen_uuid(8);
307            $binName = $binPrefix.(string)($i+(int)$binStartingNumber);
308            $stmt = $this->storeDB->prepare("INSERT INTO bsBins (uuid, name, dateCreated, ageDate, location) VALUES (:uuid, :name, CURRENT_TIMESTAMP , CURRENT_TIMESTAMP , :location)");
309            $stmt->bindValue(":uuid", $uuid);
310            $stmt->bindValue(":name", $binName);
311            $stmt->bindValue(":location", $locationID);
312            if($stmt->execute()) {
313                $id = $this->storeDB->lastInsertId();
314                $this->log->LogDebug("Insert ID: ".$id);
315                $tempBin = array("id" => $id, "quantity" => $labelQuantity);
316                $binIDArray[] = $tempBin;
317            } else {
318                ob_start();
319                print_r($stmt->errorInfo());
320                $result = ob_get_clean();
321                $this->log->LogDebug($result);
322                return false;
323            }
324
325        }
326        $this->storeDB->commit();
327
328        $jobUUID = $this->createReprintJob($binIDArray);
329        $entryData = array(
330            'action' => 'printBackstockBin',
331            'category' => $this->store->getTypeNum(),
332            'buyID' => $jobUUID
333        );
334        sendEncodedData($entryData);
335        return true;
336    }
337
338
339}