latest update
[namibia] / module / Stock / src / Stock / Utility / BulkImportHelper.php
1 <?php
2 namespace Stock\Utility;
3
4 use Doctrine\ORM\EntityManager;
5 use Utility\Debug;
6 use Workspace\Service\DataBin as DataBinCore;
7
8
9 /**
10  * Class BulkImportHelper
11  * @package Stock\Utility
12  */
13 class BulkImportHelper extends DataBinCore
14 {
15
16
17
18         /**
19          * @var \Doctrine\ORM\EntityManager
20          */
21         protected $em;
22         /**
23          * @var \Stock\Utility\ImportUtility
24          */
25         protected $util;
26         /**
27          * @var \Stock\Utility\DataStore
28          */
29         protected $store;
30         /**
31          * @var bool
32          */
33         protected $simulateExecution = false;
34         /**
35          * @var array
36          */
37         protected $categoryMap = array(
38                 'T' => 1,
39                 'A' => 2,
40                 'C' => 3,
41                 'B' => 4,
42                 'M' => 5,
43                 'H' => 6,
44                 'Z' => 7
45         );
46         /**
47          * @var array
48          */
49         protected $typeFieldsToMatch = array(
50                 'cylinders', 'cubicCapacity', 'kilowatts', 'bodyType', 'doors'
51         );
52         /**
53          * @var array
54          */
55         protected $numericFields = array(
56                 'cylinders', 'cubicCapacity', 'kilowatts', 'doors'
57         );
58         /**
59          * @var array
60          */
61         protected $makes = array();
62         /**
63          * @var array
64          */
65         protected $models = array();
66
67     /**
68      * @var array
69      */
70     public $errors = array();
71
72         public function __construct(EntityManager $em, DataStore &$store)
73         {
74                 $this->em    = $em;
75                 $this->util  = new ImportUtility($this->em);
76                 $this->store = $store;
77         $this->errors = array();
78         }
79
80
81         #-------------------------------------------------------------------------- SECTION
82         /**
83          * @param $fileName
84          */
85         public function executeOfflineTransunionDataImport($fileName)
86         {
87                 if ($this->simulateExecution)
88                 {
89                         error_log('php /var/www/namibia/public/index.php vehicle import '
90                                   . $fileName
91                                   . ' >>/log/php.log &');
92                 }
93                 else
94                 {
95                         exec(
96                                 'php /var/www/namibia/public/index.php vehicle import '
97                                 . $fileName
98                                 . ' >>/log/php.log &'
99                         );
100                 }
101         }
102
103
104         #-------------------------------------------------------------------------- SECTION
105         /**
106          * Ensure that synchronization versions have a full sequence.
107          * return null
108          */
109         public function ensureSynchronizationVersionSequence()
110         {
111                 #-> Get current latest versions.
112                 $makeVersion  = $this->util->getLatestSynchVersion('Stock\\Entity\\Make');
113                 $modelVersion = $this->util->getLatestSynchVersion('Stock\\Entity\\Model');
114                 $typeVersion  = $this->util->getLatestSynchVersion('Stock\\Entity\\Type');
115
116                 #-> Establish highest current version.
117                 $maxVersion = $this->getMaxVersion($makeVersion, $modelVersion, $typeVersion);
118
119                 #-> Where do we need updates?
120                 if ($maxVersion > $makeVersion)
121                 {
122                         $this->updateSynchVersionSequence('Stock\\Entity\\Make', $makeVersion + 1, $maxVersion);
123                 }
124                 if ($maxVersion > $modelVersion)
125                 {
126                         $this->updateSynchVersionSequence('Stock\\Entity\\Model', $modelVersion + 1, $maxVersion);
127                 }
128                 if ($maxVersion > $typeVersion)
129                 {
130                         $this->updateSynchVersionSequence('Stock\\Entity\\Type', $typeVersion + 1, $maxVersion);
131                 }
132         }
133
134         /**
135          * @param $makeVersion
136          * @param $modelVersion
137          * @param $typeVersion
138          * @return mixed
139          */
140         public function getMaxVersion($makeVersion, $modelVersion, $typeVersion)
141         {
142                 $maxVersion = $makeVersion > $modelVersion
143                         ? $makeVersion
144                         : $modelVersion;
145                 $maxVersion = $maxVersion > $typeVersion
146                         ? $maxVersion
147                         : $typeVersion;
148                 return $maxVersion;
149         }
150
151         /**
152          * @param string  $entityName
153          * @param integer $startVersion
154          * @param integer $endVersion
155          * @throws \Exception
156          */
157         public function updateSynchVersionSequence($entityName, $startVersion, $endVersion)
158         {
159                 #-> Get entries we can update.
160                 $numEntriesNeeded     = ((int)$endVersion) - ((int)$startVersion) + 1;
161                 $entries              = $this->em->getRepository($entityName)
162                         ->findBy(
163                                 array('updateVersion' => null),
164                                 array('id' => 'ASC'),
165                                 $numEntriesNeeded,
166                                 0
167                         );
168                 $this->store->version = ((int)$startVersion) + 1;
169                 if ($numEntriesNeeded != count($entries))
170                 {
171                         throw new \Exception(
172                                 'Cannot synchronize data versions on ' . $entityName . '. Not enough entries available.'
173                         );
174                 }
175                 foreach ($entries as $entry)
176                 {
177                         $entry->updateVersion = $this->store->version;
178                         $this->store->version++;
179                 }
180                 $this->em->flush();
181         }
182
183
184         #-------------------------------------------------------------------------- SECTION
185         /**
186          * MAKE THIS PUBLIC!!!!!!
187          * @param array $packet
188          * @return array
189          */
190         public function cleanupNumericInputFields(array $packet)
191         {
192                 foreach ($this->numericFields as $field)
193                 {
194                         if (array_key_exists($field, $packet))
195                         {
196                                 $packet[$field] = ('' == $packet[$field])
197                                         ? null
198                                         : $packet[$field];
199                         }
200                 }
201                 return $packet;
202         }
203
204     #-------------------------------------------------------------------------- SECTION
205
206     /**
207      * MAKE THIS PUBLIC!!!!!!
208      * @param array $packet
209      * @return mixed
210      */
211     public function getYearEntry($vehicleYear)
212     {
213         $yearId = $this->util->getId(
214             'Stock\\Entity\\Year',
215             array(
216                 'name' => $vehicleYear
217             )
218         );
219         if (false == $yearId)
220         {
221             array_push($this->errors,array('Could not find Year ' . $vehicleYear));
222
223             return $this->errors;
224
225 //            throw new \Exception(
226 //                'Could not find Year ' . $vehicleYear
227 //            );
228         }
229         return $yearId;
230     }
231
232         #-------------------------------------------------------------------------- SECTION
233
234         /**
235          * MAKE THIS PUBLIC!!!!!!
236          * @param array $packet
237          * @return mixed
238          */
239         public function getMakeEntry($vehicleMmCode,$modelId)
240         {
241         $makeId = false;
242
243         $makeEntity = $this->em->createQuery(
244             'SELECT model.id as MODELID,model.name as MODELNAME,make.id as MAKEID '
245             . 'FROM Stock\\Entity\\Model model '
246             . 'LEFT JOIN model.make make '
247             . 'WHERE model.id = :ModelId '
248             . 'AND model.archived = :Archived '
249         )
250             ->setParameter('ModelId', $modelId)
251             ->setParameter('Archived', false)
252             ->getScalarResult();
253
254         foreach($makeEntity as $make)
255         {
256 //            \Utility\Debug::errorLog('$model', $model);
257
258             $makeId = $make['MAKEID'];
259         }
260
261         if (false == $makeId)
262         {
263             array_push($this->errors,array('Could not find Make for MM Code ' . $vehicleMmCode));
264
265             return $this->errors;
266
267 //            throw new \Exception(
268 //                'Could not find Model ' . $vehicleModel
269 //            );
270         }
271         return $makeId;
272         }
273
274     #-------------------------------------------------------------------------- SECTION
275
276     /**
277      * @param array $packet
278      * @param       $makeId
279      * @return mixed
280      */
281     public function getCategoryEntry($vehicleMmCode,$typeId)
282     {
283         $categoryId = false;
284
285         $categoryEntity = $this->em->createQuery(
286             'SELECT type.id as TYPEID,category.id as CATEGORYID,category.name as CATEGORYNAME '
287             . 'FROM Stock\\Entity\\Type type '
288             . 'LEFT JOIN type.category category '
289             . 'WHERE type.id = :TypeId '
290             . 'AND category.archived = :Archived '
291         )
292             ->setParameter('TypeId', $typeId)
293             ->setParameter('Archived', false)
294             ->getScalarResult();
295
296         foreach($categoryEntity as $category)
297         {
298 //            \Utility\Debug::errorLog('$model', $model);
299
300             $categoryId = $category['CATEGORYID'];
301         }
302
303         if (false == $categoryId)
304         {
305             array_push($this->errors,array('Could not find Category for MM Code ' . $vehicleMmCode));
306
307             return $this->errors;
308
309 //            throw new \Exception(
310 //                'Could not find Model ' . $vehicleModel
311 //            );
312         }
313         return $categoryId;
314     }
315
316         #-------------------------------------------------------------------------- SECTION
317
318         /**
319          * @param array $packet
320          * @param       $makeId
321          * @return mixed
322          */
323         public function getModelEntry($vehicleMmCode,$typeId)
324         {
325         $modelId = false;
326
327         $modelEntity = $this->em->createQuery(
328             'SELECT type.id as TYPEID,model.id as MODELID,model.name as MODELNAME '
329             . 'FROM Stock\\Entity\\Type type '
330             . 'LEFT JOIN type.model model '
331             . 'WHERE type.id = :TypeId '
332             . 'AND model.archived = :Archived '
333         )
334             ->setParameter('TypeId', $typeId)
335             ->setParameter('Archived', false)
336             ->getScalarResult();
337
338         foreach($modelEntity as $model)
339         {
340 //            \Utility\Debug::errorLog('$model', $model);
341
342             $modelId = $model['MODELID'];
343         }
344
345                 if (false == $modelId)
346                 {
347             array_push($this->errors,array('Could not find Model for MM Code' . $vehicleMmCode));
348
349             return $this->errors;
350
351 //            throw new \Exception(
352 //                'Could not find Model ' . $vehicleModel
353 //            );
354                 }
355                 return $modelId;
356         }
357
358
359         #-------------------------------------------------------------------------- SECTION
360         /**
361          * @param array $packet
362          * @param $modelId
363          * @return mixed
364          * @throws \Doctrine\ORM\ORMException
365          */
366         public function getVehicleType($vehicleMmCode,$vehicleMake)
367         {
368         $typeId = false;
369                 #-> Do data preparations.
370                 /**
371                  * Here we ensure that we remove spaces and retain leading zeroes to prevent data duplication.
372                  * Previously, this field was cast to int which lead to duplications. - FP
373                 */
374         $vehicleMmCode = (string)$vehicleMmCode;
375         $vehicleMmCode = preg_replace('/\s+/', '', $vehicleMmCode);
376
377 //              #-> Find entry.
378 //        $typeId = $this->util->getId(
379 //            'Stock\\Entity\\Type',
380 //            array(
381 //                'mmCode' => $vehicleMmCode
382 //            )
383 //        );
384
385         $typeEntity = $this->em->createQuery(
386             'SELECT type.id as TYPEID,type.name as TYPENAME '
387             . 'FROM Stock\\Entity\\Type type '
388             . 'WHERE type.mmCode = :MmCode '
389             . 'AND type.archived = :Archived '
390         )
391             ->setParameter('MmCode', $vehicleMmCode)
392             ->setParameter('Archived', false)
393             ->getScalarResult();
394
395         foreach($typeEntity as $type)
396         {
397 //            \Utility\Debug::errorLog('$type', $type);
398
399             $typeId = $type['TYPEID'];
400         }
401
402                 if (false == $typeId)
403                 {
404             array_push($this->errors,array('Could not find Type for MM Code ' .$vehicleMmCode));
405
406             return $this->errors;
407 //            throw new \Exception(
408 //                'Could not find Type for MM Code ' .$vehicleMmCode
409 //            );
410                 }
411                 return $typeId;
412         }
413
414
415
416     #-------------------------------------------------------------------------- SECTION
417
418     /**
419      * @param array $packet
420      * @param       $makeId
421      * @return mixed
422      */
423     public function getInteriorColourEntry($colour)
424     {
425         $colourId = false;
426
427         $colourEntity = $this->em->createQuery(
428             'SELECT interiorColour.id,interiorColour.name '
429             . 'FROM Stock\\Entity\\InteriorColour interiorColour '
430             . 'WHERE interiorColour.archived = :Archived '
431         )
432             ->setParameter('Archived', false)
433             ->getScalarResult();
434
435         foreach($colourEntity as $colours)
436         {
437             if (strpos(strtolower($colour), strtolower($colours['name'])) !== false)
438             {
439                 $colourId = $colours['id'];
440             }
441         }
442
443         if(false != $colourId)
444         {
445             return $colourId;
446         }
447
448 //        if (false == $colourId)
449 //        {
450 //            array_push($this->errors,array('Could not find colour ' . $colour));
451 //
452 //            return $this->errors;
453 //
454 ////            throw new \Exception(
455 ////                'Could not find colour ' . $colour
456 ////            );
457 //        }
458 //        return $colourId;
459     }
460
461     #-------------------------------------------------------------------------- SECTION
462
463     /**
464      * @param array $packet
465      * @param       $makeId
466      * @return mixed
467      */
468     public function getUpholsteryEntry($upholstery)
469     {
470         if('cloth' == strtolower($upholstery))
471         {
472             $upholstery = 'Material';
473         }
474
475         $upholsteryId = false;
476
477         $upholsteryEntity = $this->em->createQuery(
478             'SELECT upholstery.id,upholstery.name '
479             . 'FROM Stock\\Entity\\Upholstery upholstery '
480             . 'WHERE upholstery.archived = :Archived '
481         )
482             ->setParameter('Archived', false)
483             ->getScalarResult();
484
485         foreach($upholsteryEntity as $upholsteries)
486         {
487             if (strpos(strtolower($upholstery), strtolower($upholsteries['name'])) !== false)
488             {
489                 $upholsteryId = $upholsteries['id'];
490             }
491         }
492
493         if(false != $upholsteryId)
494         {
495             return $upholsteryId;
496         }
497 //        if (false == $upholsteryId)
498 //        {
499 //            array_push($this->errors,array('Could not find upholstery ' . $upholstery));
500 //
501 //            return $this->errors;
502 //
503 ////            throw new \Exception(
504 ////                'Could not find colour ' . $upholstery
505 ////            );
506 //        }
507 //        return $upholsteryId;
508     }
509
510     #-------------------------------------------------------------------------- SECTION
511
512     /**
513      * @param array $packet
514      * @param       $makeId
515      * @return mixed
516      */
517     public function getConditionEntry($condition)
518     {
519         $condition = substr($condition, 1);
520
521         $conditionId = false;
522
523         $conditionEntity = $this->em->createQuery(
524             'SELECT condition.id,condition.name '
525             . 'FROM Stock\\Entity\\Condition condition '
526             . 'WHERE condition.name LIKE :Condition '
527             . 'AND condition.archived = :Archived '
528         )
529             ->setParameter('Condition', $condition.'%')
530             ->setParameter('Archived', false)
531             ->getScalarResult();
532
533         foreach($conditionEntity as $conditions)
534         {
535 //            \Utility\Debug::errorLog('$conditions', $conditions);
536
537             $conditionId = $conditions['id'];
538         }
539
540         if(false != $conditionId)
541         {
542             return $conditionId;
543         }
544
545 //        if (false == $conditionId)
546 //        {
547 //            array_push($this->errors,array('Could not find condition ' . $condition));
548 //
549 //            return $this->errors;
550 //
551 ////            throw new \Exception(
552 ////                'Could not find condition ' . $condition
553 ////            );
554 //        }
555 //        return $conditionId;
556     }
557
558     #-------------------------------------------------------------------------- SECTION
559
560     /**
561      * @param array $packet
562      * @param       $makeId
563      * @return mixed
564      */
565     public function getTransmissionEntry($transmission)
566     {
567         $transmissionId = false;
568
569         $transmissionEntity = $this->em->createQuery(
570             'SELECT transmissionType.id,transmissionType.name '
571             . 'FROM Stock\\Entity\\TransmissionType transmissionType '
572             . 'WHERE transmissionType.name = :TransmissionType '
573             . 'AND transmissionType.archived = :Archived '
574         )
575             ->setParameter('TransmissionType', $transmission)
576             ->setParameter('Archived', false)
577             ->getScalarResult();
578
579         foreach($transmissionEntity as $transmissions)
580         {
581 //            \Utility\Debug::errorLog('$transmissions', $transmissions);
582
583             $transmissionId = $transmissions['id'];
584         }
585
586         if(false != $transmissionId)
587         {
588             return $transmissionId;
589         }
590
591 //        if (false == $transmissionId)
592 //        {
593 //            array_push($this->errors,array('Could not find transmission ' . $transmission));
594 //
595 //            return $this->errors;
596 //
597 //        }
598 //        return $transmissionId;
599     }
600
601     #-------------------------------------------------------------------------- SECTION
602
603     /**
604      * @param array $packet
605      * @param       $makeId
606      * @return mixed
607      */
608     public function getFuelTypeEntry($fuelType)
609     {
610         $fuelTypeId = false;
611
612         $fuelTypeEntity = $this->em->createQuery(
613             'SELECT fuelType.id,fuelType.name '
614             . 'FROM Stock\\Entity\\FuelType fuelType '
615             . 'WHERE fuelType.name = :FuelType '
616             . 'AND fuelType.archived = :Archived '
617         )
618             ->setParameter('FuelType', $fuelType)
619             ->setParameter('Archived', false)
620             ->getScalarResult();
621
622         foreach($fuelTypeEntity as $fuelTypes)
623         {
624 //            \Utility\Debug::errorLog('$fuelTypes', $fuelTypes);
625
626             $fuelTypeId = $fuelTypes['id'];
627         }
628
629         if(false != $fuelTypeId)
630         {
631             return $fuelTypeId;
632         }
633
634 //        if (false == $fuelTypeId)
635 //        {
636 //            array_push($this->errors,array('Could not find fuel type ' . $fuelType));
637 //
638 //            return $this->errors;
639 //        }
640 //        return $fuelTypeId;
641     }
642
643     #-------------------------------------------------------------------------- SECTION
644
645     /**
646      * @param array $packet
647      * @param       $makeId
648      * @return mixed
649      */
650     public function getExteriorColourEntry($colour)
651     {
652         $colourId = false;
653
654         $colourEntity = $this->em->createQuery(
655             'SELECT exteriorColour.id,exteriorColour.name '
656             . 'FROM Stock\\Entity\\ExteriorColour exteriorColour '
657             . 'WHERE exteriorColour.archived = :Archived '
658         )
659             ->setParameter('Archived', false)
660             ->getScalarResult();
661
662         foreach($colourEntity as $colours)
663         {
664             if (strpos(strtolower($colour), strtolower($colours['name'])) !== false)
665             {
666                 $colourId = $colours['id'];
667             }
668         }
669
670         if(false != $colourId)
671         {
672             return $colourId;
673         }
674
675 //        if (false == $colourId)
676 //        {
677 //            array_push($this->errors,array('Could not find colour ' . $colour));
678 //
679 //            return $this->errors;
680 //
681 ////            throw new \Exception(
682 ////                'Could not find colour ' . $colour
683 ////            );
684 //        }
685 //        return $colourId;
686     }
687
688         /**
689          * @param array $packet
690          * @param array $years
691          * @return array
692          * @throws \Doctrine\ORM\ORMException
693          */
694         public function prepareDateVehicleTypeData(array $packet, $years)
695         {
696                 list($introMonth, $introYear) = explode('/', $packet['IntroDate']);
697                 $discontinueYear  = false;
698                 $discontinueMonth = false;
699                 if (!empty($packet['DiscDate']))
700                 {
701                         list($discontinueMonth, $discontinueYear) = explode('/', $packet['DiscDate']);
702                 }
703                 unset($packet['IntroDate']);
704                 unset($packet['DiscDate']);
705                 $packet['introYear']  = $this->em->getReference(
706                         '\Stock\Entity\Year',
707                         $years[$introYear]
708                 );
709                 $packet['introMonth'] = $introMonth;
710                 $packet['discYear']   = null;
711                 if ($discontinueYear)
712                 {
713                         $packet['discYear']  = $this->em->getReference(
714                                 'Stock\\Entity\\Year', $years[$discontinueYear]
715                         );
716                         $packet['discMonth'] = $discontinueMonth;
717                         return $packet;
718                 }
719                 return $packet;
720         }
721
722         /**
723          * @param array $packet
724          * @param       $modelId
725          * @return array
726          * @throws \Doctrine\ORM\ORMException
727          */
728         public function prepareVehicleTypeDataForNewEntry(array $packet, $modelId)
729         {
730                 $packet['VehicleType']   = $this->em->getReference(
731                         'Stock\\Entity\\Category',
732                         $this->categoryMap[$packet['VehicleType']]
733                 );
734                 $packet['Model']         = $this->em->getReference(
735                         '\Stock\\Entity\\Model',
736                         $modelId
737                 );
738                 $packet['name']          = $packet['Variant'];
739                 $packet['createVersion'] = $this->store->version;
740                 $packet['updateVersion'] = $this->store->version;
741                 return $packet;
742         }
743
744         /**
745          * @param array $packet
746          * @param       $type
747          * @return bool
748          */
749         public function vehicleTypeUpdateIsNeeded(array $packet, $type)
750         {
751                 $needUpdate = false;
752                 foreach ($this->typeFieldsToMatch as $field)
753                 {
754                         if ($packet[$field] != $type->$field)
755                         {
756                                 $needUpdate   = true;
757                                 $type->$field = $packet[$field];
758                         }
759                         if (!$needUpdate)
760                         {
761                                 if (false != $packet['discYear'] && is_null($type->discYear))
762                                 {
763                                         $needUpdate      = true;
764                                         $type->discYear  = $packet['discYear'];
765                                         $type->discMonth = $packet['discMonth'];
766                                 }
767                         }
768                 }
769                 return $needUpdate;
770         }
771
772
773         #-------------------------------------------------------------------------- SECTION
774         /**
775          * @return null
776          */
777         public function processBatch()
778         {
779                 usleep(500);
780                 $this->em->flush();
781                 $this->em->commit();
782                 $this->em->clear();
783                 $this->em->getConnection()->close();
784                 $this->em->beginTransaction();
785                 $this->store->version++;
786                 $this->store->numItems = 0;
787         }
788
789 }