initial commit
[namibia] / module / Stock / src / Stock / Service / Stock.php
1 <?php
2 namespace Stock\Service;
3
4
5
6 /**
7  * Manage stock data.
8  * @author andre.fourie
9  */
10
11 class Stock extends \Stock\DataBin\Stock
12 {
13
14
15         /**
16          * Initialize a new item.
17          * @param \Stock\Entity\Stock $stock
18          */
19         public function initNewItem(\Stock\Entity\Stock $stock) { }
20
21         /**
22          * Route newly added item to initial state.
23          * @param \Stock\Entity\Stock $stock
24          * @param string|null $previousState
25          * @param array|null $routingData
26          * @return string
27          */
28         public function routeNewItem(\Stock\Entity\Stock $stock, $previousState, $routingData)
29         {
30                 if (\Utility\Registry::checkOnce('NewStockItem.FromValuation'))
31                 {
32                         return 'This.Valuation';
33                 }
34                 return array(
35                                 'Destination' => \Utility\Registry::checkOnce('NewStockItem.Status', 'This.Stock'),
36                                 'Data' => \Utility\Registry::checkOnce('Service.Stock.Context', array())
37                 );
38         }
39
40         /**
41          * Route to Retail and set reset time.
42          * @param \Stock\Entity\Stock $stock
43          * @param string $previousState
44          */
45         public function directRouteSendToRetail(\Stock\Entity\Stock $stock, $previousState)
46         {
47                 $stock->reset = new \DateTime(date('Y-m-d H:i:s', time() + 86400));
48                 $this->em->flush();
49                 return 'This.Retail';
50         }
51
52
53         /**
54          * Route to Trade Centre
55          * @param \Stock\Entity\Stock $stock
56          * @param string $previousState
57          */
58         public function directRouteSendToTradeCenter(\Stock\Entity\Stock $stock, $previousState)
59         {
60
61                 //Write hit to Stats logs (need stock or valuation stock id and profile id)
62                 $today = new \DateTime();
63                 //$test = "123";
64                 //\Utility\Debug::errorLog('directRouteSendToTradeCenter new', $test);
65
66                 $em = \Utility\Registry::getEntityManager();
67                 $loghit = new \Statistical\Entity\Statistical();
68                 $loghitData = array(
69                                 'stock'                 => $em->getRepository('\Stock\Entity\Stock')->find($stock->id),
70                                 'dealdone'                      => false,
71                                 'dealnotdone'           => false,
72                                 'tradecentre'           => true,
73                                 'fromProfile'           => $em->getRepository('\User\Entity\Profile')->find($stock->createdBy->id),
74                                 'created'               => $today
75                 );
76
77                 $loghit->fromArray($loghitData);
78                 $em->persist($loghit);
79                 $em->flush();
80
81                 return 'This.TradeCenter';
82         }
83
84         /**
85          * Route to Retail and set reset time..
86          * @param \Stock\Entity\Stock $stock
87          * @param string $previousState
88          */
89         public function directRouteReclaimFromRetail(\Stock\Entity\Stock $stock, $previousState)
90         {
91                 $stock->reset = null;
92                 $this->em->flush();
93                 return 'This.Stock';
94         }
95
96         /**
97          * Route item that is received back from Auction Workflow.
98          * @param \Stock\Entity\Stock $stock
99          * @param string $previousState
100          * @param array|null $routingData
101          */
102         public function routeAuctionHandover(\Stock\Entity\Stock $stock, $previousState, $routingData)
103   {
104                 if ('Sold' == $stock->auction->jobState
105                         || (time() > $stock->auction->endDate->getTimestamp()
106                                 && $stock->auction->reservePrice < $stock->auction->currentBidPrice && 'Undone' != $stock->auction->jobState))
107                 {
108       $this->em->flush();
109                         return 'This.Sold';
110                 }
111     
112     if ($stock->previousState == 'Trade Center')
113     {
114       $stock->previousState = 'Auction';
115       $this->em->flush();
116       return 'This.TradeCenter';
117     }
118     else
119     {
120       $stock->previousState = 'Auction';
121       $this->em->flush();
122       return 'This.Stock';
123     }
124         }
125
126         /**
127          * ExecuteAfter: Create.
128          * Add item to queue for mobile.
129          * @param array $meta
130          * @param object|null $jobRecord
131          * @param object|null $record
132          * @param \Workspace\Utility\ServiceInputParams $contract
133          * @return array
134          */
135         public function generateHistoryList($meta, $jobRecord, $record, \Workspace\Utility\ServiceInputParams $contract)
136         {
137                 $record = null == $jobRecord
138                         ? $record->toArray()
139                         : $jobRecord->toArray();
140
141                 $StockID = $record['id'];
142                 $stockTypeID = $record['type'];
143
144                 #-> Clear any existing history for this vehicle.
145                 $this->em->createQuery(
146                                 'DELETE FROM \Stock\Entity\PricingHistory pricingHistory '
147                                 . 'WHERE pricingHistory.stockId = '
148                                 . $StockID
149                                 )
150                         ->execute();
151
152                 #-> Establish history.
153                 $result = $this->em->createQuery(
154                                 'SELECT stock, st, vy '
155                                 . 'FROM \Stock\Entity\Stock stock '
156                                 . 'LEFT JOIN stock.type st '
157                                 . 'LEFT JOIN stock.vehicleYear vy '
158                                 . 'WHERE stock.id = :StockID '
159                         )
160                         ->setParameter('StockID', $StockID)
161                         ->getArrayResult();
162
163                 $stockTypeID = $result[0]['type']['id'];
164                 $vehicleYearID = $result[0]['vehicleYear']['id'];
165
166
167                 $today = new \DateTime();
168                 $dateFrom = clone $today;
169                 $dateFrom->modify('-3 months');
170
171                 $result = $this->em->createQuery(
172                                 'SELECT stock, priceguide, auction, st, po, cb, bids '
173                                 . 'FROM \Stock\Entity\Stock stock '
174                                 . 'LEFT JOIN stock.priceGuide priceguide WITH priceguide.created BETWEEN :dateFrom AND :dateTo '
175                                 . 'LEFT JOIN stock.auction auction WITH auction.created BETWEEN :dateFrom AND :dateTo '
176                                 . 'LEFT JOIN stock.type st '
177                                 . 'LEFT JOIN priceguide.offers po '
178                                 . 'LEFT JOIN auction.currentBid cb '
179                                 . 'LEFT JOIN auction.bids bids '
180                                 . 'WHERE st.id = :stockTypeID '
181                                 . 'AND IDENTITY(stock.vehicleYear) = :vehicleYearID '
182                                 . 'AND (stock.highestBid > 0 OR stock.highestOffer > 0) '
183                                 . 'AND stock.archived = 0 '
184                                 . 'ORDER by auction.created, priceguide.created ASC '
185                         )
186                         ->setParameter('stockTypeID', $stockTypeID)
187                         ->setParameter('vehicleYearID', $vehicleYearID)
188                         ->setParameter('dateFrom', $dateFrom)
189                         ->setParameter('dateTo', $today)
190                         ->getArrayResult();
191
192                 $i = 0;
193                 $x = 0;
194                 $existing = array();
195                 foreach ($result as $pricingHistory)
196                 {
197                         $StockDamageTotal = $pricingHistory['damageTotal'];
198                         $StockTradePrice = $pricingHistory['tradePrice'];
199             $StockListPrice = $pricingHistory['listPrice'];
200                         $StockKMS = $pricingHistory['km'];
201                         if ($StockKMS == '' || is_null($StockKMS))
202                         {
203                                 $StockKMS = 0;
204                         }
205                         // price guide
206                         $PriceguideHighestOffer = $pricingHistory['highestOffer'];
207                         // Auction
208                         $highestBid = $pricingHistory['highestBid'];
209
210                         // Priceguide && Auction
211                         if ($PriceguideHighestOffer != 0 && $highestBid != 0 )
212                         {
213                                 $priceGuideOffers = $pricingHistory['priceGuide']['offers'];
214                                 if (is_array($priceGuideOffers))
215                                 {
216                                         $highestAmnt = 0.0;
217                                         foreach ($priceGuideOffers as $priceGuideOffer)
218                                         {
219                                                 if ($priceGuideOffer['amount'] > $highestAmnt)
220                                                 {
221                                                         $highestAmnt = $priceGuideOffer['amount'];
222                                                         $priceGuideOffersCreatedDate = $priceGuideOffer['created'];
223                                                 }
224                                         }
225
226                                         $data = array(
227                                                         'date'                                  => $priceGuideOffersCreatedDate,
228                                                         'trade'                                 => $StockTradePrice,
229                             'listPrice'                         => $StockListPrice,
230                                                         'totalRecon'                    => $StockDamageTotal,
231                                                         'km'                                    => $StockKMS,
232                                                         'pricegOffer'                   => $PriceguideHighestOffer,
233                                                         'auctionWinningBid'     => $highestBid,
234                                                         'stockId'                               => $StockID
235                                         );
236                                         $hash = md5(serialize($data));
237                                         if (!isset($existing[$hash]))
238                                         {
239                                                 $existing[$hash] = true;
240                                                 $entry = new \Stock\Entity\PricingHistory();
241                                                 $entry->fromArray($data);
242                                                 $this->em->persist($entry);
243                                                 $this->em->flush($entry);
244                                                 $x++;
245                                         }
246                                 }
247                         }
248                         // Price Guide only
249                         if ($PriceguideHighestOffer != 0 && $highestBid == 0 )
250                         {
251                                 $priceGuideOffers = $pricingHistory['priceGuide']['offers'];
252                                 if (is_array($priceGuideOffers))
253                                 {
254                                         $highestAmnt = 0.0;
255                                         foreach ($priceGuideOffers as $priceGuideOffer)
256                                         {
257                                                 if ($priceGuideOffer['amount'] > $highestAmnt)
258                                                 {
259                                                         $highestAmnt = $priceGuideOffer['amount'];
260                                                         $priceGuideOffersCreatedDate = $priceGuideOffer['created'];
261                                                 }
262                                         }
263                                         $data = array(
264                                                         'date'                                  => $priceGuideOffersCreatedDate, // changes all the time
265                                                         'trade'                                 => $StockTradePrice,
266                             'listPrice'                         => $StockListPrice,
267                                                         'totalRecon'                    => $StockDamageTotal,
268                                                         'km'                                    => $StockKMS,
269                                                         'pricegOffer'                   => $PriceguideHighestOffer,
270                                                         'auctionWinningBid'     => 0.0,
271                                                         'stockId'                               => $StockID
272
273                                         );
274                                         $hash = md5(serialize($data));
275                                         if (!isset($existing[$hash]))
276                                         {
277                                                 $existing[$hash] = true;
278                                                 $entry = new \Stock\Entity\PricingHistory();
279                                                 $entry->fromArray($data);
280                                                 $this->em->persist($entry);
281                                                 $this->em->flush($entry);
282                                                 $x++;
283                                         }
284                                 }
285                         }
286
287                         // Auction only
288                         if ($PriceguideHighestOffer == 0 && $highestBid != 0)
289                         {
290                                 $date = $pricingHistory['auction']['created'];
291                                 $data = array(
292                                                 'date'                                  => $date, // changes all the time
293                                                 'trade'                                 => $StockTradePrice,
294                         'listPrice'                             => $StockListPrice,
295                                                 'totalRecon'                    => $StockDamageTotal,
296                                                 'km'                                    => $StockKMS,
297                                                 'pricegOffer'                   => 0.0,
298                                                 'auctionWinningBid'     => $highestBid,
299                                                 'stockId'                               => $StockID
300                                 );
301                                 $hash = md5(serialize($data));
302                                 if (!isset($existing[$hash]))
303                                 {
304                                         $existing[$hash] = true;
305                                         $entry = new \Stock\Entity\PricingHistory();
306                                         $entry->fromArray($data);
307                                         $this->em->persist($entry);
308                                         $this->em->flush($entry);
309                                         $x++;
310                                 }
311                         }
312
313                         if ($x > 10)
314                         {
315                                 break;
316                         }
317                 }
318         }
319
320         public function updateCustomVehicles($meta, $jobRecord, $contract, $data)
321         {
322                 $contract->data = $this->addCustomVehicles($meta, $contract->data);
323                 return $contract->data;
324         }
325
326         /**
327          * ExecuteBefore: Create
328          * @param array $meta
329          * @param array $data
330          */
331         public function addCustomVehicles($meta, $data)
332         {
333                 #-> Check if we have a custom vehicle
334                 if ($data->Stock['category'] == '8')
335                 {
336                         #-> Get latest version.
337                         $versions = $this->em->createQuery(
338                                         'SELECT MAX(vehicleType.createVersion) AS createVersion,'
339                                         . ' MAX(vehicleType.updateVersion) AS updateVersion '
340                                         . 'FROM Stock\\Entity\\Type vehicleType'
341                                 )
342                                 ->getScalarResult();
343                         $newVersion = $versions[0]['createVersion'] > $versions[0]['updateVersion']
344                                 ? $versions[0]['createVersion'] + 1
345                                 : $versions[0]['updateVersion'] + 1;
346
347                         #-> Create make, model, type entries
348                         $makeManual = $data->Stock['makeManual'];
349                         $modelManual = $data->Stock['modelManual'];
350                         $typeManual = $data->Stock['typeManual'];
351                         $category = $data->Stock['category'];
352                         $today = new \DateTime();
353                         $em = \Utility\Registry::getEntityManager();
354
355       error_log('Make: ' . $data->Stock['make'] . ' New: ' . $makeManual . "/n");
356       error_log('Model: ' . $data->Stock['model'] . ' New: ' . $modelManual . "/n");
357       error_log('Type: ' . $data->Stock['type'] . ' New: ' . $typeManual . "/n");
358                         // Make
359                         // Do a check if this make exists
360                         if ('' != $makeManual && $makeManual != $data->Stock['make'])
361                         {
362                                 $make = $em->getRepository('\Stock\Entity\Make')
363                                         ->findOneBy(array(
364                                                         'name' => $makeManual
365                                         ));
366
367                                 if (is_null($make))
368                                 {
369                                         // Else add Make Manual
370                                         $make = new \Stock\Entity\Make();
371                                         $makeData = array(
372                                                         'name'                  => $makeManual,
373                                                         'created'                       => $today,
374                                                         'createVersion'         => $newVersion
375                                         );
376
377                                         $make->fromArray($makeData);
378                                         $em->persist($make);
379                                         $em->flush();
380                                 }
381                                 // get make id back
382                                 $makeId = $make->id;
383                         }
384                         else
385                         {
386                                 $makeId = $data->Stock['make'];
387                         }
388
389
390                         // Model
391                         if ('' != $modelManual && $modelManual != $data->Stock['model'])
392                         {
393                                 // Do a check if this model exists
394                                 $model = $em->getRepository('\Stock\Entity\Model')
395                                         ->findOneBy(array(
396                                                         'make' => $makeId,
397                                                         'name' => $makeManual
398                                         ));
399
400                                 if (is_null($model))
401                                 {
402                                         // Add Model Manual
403                                         $model = new \Stock\Entity\Model();
404                                         $modelData = array(
405                                                         'make'                  => $em->getRepository('\Stock\Entity\Make')->find($makeId),
406                                                         'name'                          => $modelManual,
407                                                         'created'                       => $today,
408                                                         'createVersion'         => $newVersion
409
410                                         );
411
412                                         $model->fromArray($modelData);
413                                         $em->persist($model);
414                                         $em->flush();
415                                 }
416                                 //get model id back
417                                 $modelId = $model->id;
418                         }
419                         else
420                         {
421                                 $modelId = $data->Stock['model'];
422                         }
423
424                         // Type
425
426                         //\Utility\Debug::errorLog('Stock $typeManual', $typeManual);
427                         if ('' != $typeManual && $typeManual != $data->Stock['type'])
428                         {
429                                 // Do a check if this type exists
430                                 $type = $em->getRepository('\Stock\Entity\Type')
431                                         ->findOneBy(array(
432                                                         'model' => $modelId,
433                                                         'category' => $category,
434                                                         'name' => $typeManual
435                                         ));
436
437                                 if (is_null($type))
438                                 {
439                                         // Add Type Manual
440                                         $type = new \Stock\Entity\Type();
441                                         $typeData = array(
442                                                         'model'                 => $em->getRepository('\Stock\Entity\Model')->find($modelId),
443                                                         'category'                      => $em->getRepository('\Stock\Entity\Category')->find($category),
444                                                         'name'                          => $typeManual,
445                                                         'mmCode'                        => 'other',
446                                                         'introYear'                     => $em->getRepository('\Stock\Entity\Year')->find(1),
447                                                         'introMonth'            => '1',
448                                                         'created'                       => $today,
449                                                         'createVersion'         => $newVersion
450
451                                         );
452
453                                         $type->fromArray($typeData);
454                                         $em->persist($type);
455                                         $em->flush();
456
457                                 }
458                                 //get model id back
459                                 $typeId = $type->id;
460                                 //\Utility\Debug::errorLog('Stock $typeId 1', $typeId);
461                                 #-> Update data with new ids
462                                 $data->Stock['type'] = $typeId;
463                         }
464
465
466                 }
467                 //\Utility\Debug::errorLog('Stock typeID 2', $data->Stock['type']);
468                 return $data;
469         }
470
471         /**
472          * CRON functionality: Upload stock images.
473          * @param array $meta
474          */
475         public function uploadImages()
476         {
477         set_time_limit(0);
478                 $stack = $this->em->getRepository('Stock\\Entity\\StockImages')
479                                 ->findBy(array(
480                                                 'archived' => 0
481                                 ));
482                 $fields = array(
483                                 'mainImage',
484                                 'frontImage',
485                                 'rightImage',
486                                 'leftImage',
487                                 'backImage',
488                                 'interiorImage',
489                                 'engineImage',
490                                 'natisImage'
491                 );
492                 $image = new \Utility\Upload\Image(array(), false);
493                 foreach ($stack as $item)
494                 {
495                         $image = new \Utility\Upload\Image(array(), false);
496
497                         foreach ($fields as $fieldBase)
498                         {
499                                 $urlField = $fieldBase . 'Url';
500                                 if (is_null($item->$fieldBase)
501                                         && !is_null($item->$urlField)
502                                         && 0 < strlen($item->$urlField))
503                                 {
504                                         $downloaded = $image->externalDownload($item->$urlField);
505                                         if ($downloaded->id)
506                                         {
507                                                 $ref = $this->em->getReference('Utility\\Entity\\Image', $downloaded->id);
508                                                 $item->$fieldBase = $ref;
509                                                 $item->stock->$fieldBase = $ref;
510                                         }
511                                 }
512                         }
513                         $item->archived = 1;
514                         $this->em->flush();
515                 }
516         }
517
518     /**
519      * CRON functionality: Clean up database
520      * - Change the status of vehicles in valuation that have a status of "New Valuation" that were loaded before $valuationDate and change status to archived
521      * - Change the status of vehicles in stock that were loaded before $stockDate and change the status to archived
522      * @param $valuationDate
523      * @param $stockDate
524      */
525     function cleanUpStockAndValuationDatabase($valuationDate,$stockDate)
526     {
527         error_log('-------------------------------------------------');
528         error_log('Database clean up for stock and valuation : START');
529
530         /*
531          * variable declaration
532          */
533 //        $valuationLookupStatus  = 'New Valuation,Pending Valuation,Complete Valuation,Stock';
534
535         $valuationLookupStatus = array('New Valuation','Pending Valuation','Complete Valuation','Stock');
536
537         $projectRoot = \Utility\Registry::getConfigParam('ProjectRootPath');
538         $output = array();
539         $execResult = 0;
540         $recordValuationCount = 0;
541         $recordStockCount = 0;
542
543         error_log('-----------------');
544         error_log('Valuation : START');
545         /*
546          * valuation update
547          */
548         $valuationEntry = $this->em->createQuery(
549             'SELECT valuation.id,valuation.jobState '
550             . 'FROM Valuation\\Entity\\Valuation valuation '
551             . 'WHERE valuation.created <= :createdDate '
552             . ' AND valuation.jobState in (:currentStatus)'
553             . ' AND valuation.jobState != :notArchived'
554             . ' AND valuation.archived = :archived'
555         )
556         ->setParameter('createdDate', $valuationDate)
557         ->setParameter('currentStatus', $valuationLookupStatus)
558         ->setParameter('notArchived', 'Archived')
559         ->setParameter('archived', 0);
560
561         \Utility\Debug::errorLog('$valuationEntry->getSQL()',$valuationEntry->getSQL());
562         \Utility\Debug::errorLog('$valuationEntry->getParameters()',$valuationEntry->getParameters());
563
564         $valuationResults = $valuationEntry->getArrayResult();
565
566         if(!empty($valuationResults))
567         {
568             foreach($valuationResults as $valuationEntryValue)
569             {
570                 $recordValuationCount++;
571
572                 exec(
573                     "php " . $projectRoot . "public/index.php clean up database worker "
574                     . $valuationEntryValue['id'] . " '" . $valuationEntryValue['jobState'] . "' valuation >>/log/php.log",
575                     $output,
576                     $execResult
577                 );
578             }
579         }
580
581                 error_log('Valuation : END');
582                 error_log('---------------');
583
584                 error_log(print_r("total valuation records " . $recordValuationCount));
585
586                 /*
587                 * stock update
588                 */
589                 error_log('-----------------');
590                 error_log('Stock : START');
591
592                 $stockEntry = $this->em->createQuery(
593                         'SELECT stock.id,stock.jobState '
594                         . 'FROM Stock\\Entity\\Stock stock '
595                         . 'WHERE stock.created <= :createdDate '
596                         . ' AND stock.jobState != :notArchived'
597                         . ' AND stock.archived = :archived'
598                 )
599                         ->setParameter('createdDate', $stockDate)
600                         ->setParameter('notArchived', 'Archived')
601                         ->setParameter('archived', 0);
602
603         \Utility\Debug::errorLog('$stockEntry->getSQL()',$stockEntry->getSQL());
604         \Utility\Debug::errorLog('$stockEntry->getParameters()',$stockEntry->getParameters());
605
606         $stockResults = $stockEntry->getArrayResult();
607
608                 if (!empty($stockResults))
609                 {
610                         foreach ($stockResults as $stockEntryValue)
611                         {
612                                 $recordStockCount++;
613
614                                 exec(
615                                         "php " . $projectRoot . "public/index.php clean up database worker "
616                                         . $stockEntryValue['id'] . " '" . $stockEntryValue['jobState'] . "' stock >>/log/php.log",
617                                         $output,
618                                         $execResult
619                                 );
620                         }
621                 }
622                 error_log('Stock : END');
623                 error_log('---------------');
624
625                 error_log(print_r("total stock records " . $recordStockCount));
626
627                 error_log('Database clean up for stock and valuation : END');
628                 error_log('-----------------------------------------------');
629
630         }
631                         
632     /**
633          * 
634          * CRON functionality: Clean up database worker
635          * - Change the status of vehicles in valuation that have a status of "New Valuation" that were loaded before
636          * $valuationDate and change status to archived
637          * - Change the status of vehicles in stock that were loaded before $stockDate and change the status to archived
638          * @param $id
639          * @param $currentStatus
640          * @param $table
641          */
642         function cleanUpStockAndValuationDatabaseWorker($id, $currentStatus, $table)
643         {
644         error_log('id : ' . $id);
645         error_log('currentStatus : ' . $currentStatus);
646         error_log('table : ' . $table);
647
648         $updateEntity = array();
649
650         if('valuation' == $table)
651         {
652             $updateEntity = $this->em->getRepository('\\Valuation\\Entity\\Valuation')
653                     ->find($id);
654         }
655
656         if('stock' == $table)
657         {
658             $updateEntity = $this->em->getRepository('\\Stock\\Entity\\Stock')
659                 ->find($id);
660         }
661
662         if(!empty($updateEntity))
663         {
664
665             try{
666                 $updateEntity->previousState = $currentStatus;
667                 $updateEntity->jobState = 'Archived';
668 //                $updateEntity->archived = 1;
669                 $this->em->persist($updateEntity);
670                 $this->em->flush();
671
672 //                error_log($id . ' updated successfully');
673             }
674             catch (\Exception $e)
675             {
676                 error_log('Error could not update ' . $table . ' with id ' . $id);
677                 error_log(print_r($e));
678             }
679
680         }
681
682         }
683
684
685
686         /**
687          * Route item to Archived state.
688          * @param \Stock\Entity\Stock $stock
689          * @param string              $previousState
690          */
691         public function directRouteMoveToArchive(\Stock\Entity\Stock $stock, $previousState)
692         {
693                 $return_value='This.Archived';
694                 $userId = \Utility\Registry::isAuthenticated()
695                         ? \Utility\Registry::getAuthParam('id')
696                         : 0;
697
698                 if((integer)$previousState!==3)
699                 {
700                         exec("php /var/www/B4C2/public/index.php stock change 3 " . $stock->id . " $userId  > /dev/null &");
701                         //undo relist
702
703                         $query=$this->em->createQuery("UPDATE Auction\Entity\Auction auction SET auction.jobState='' WHERE auction.stock='".$stock->id."' ");
704                         $query->getResult();
705                 }
706
707
708                 return $return_value;
709         }
710
711         /**
712          * Route item to Archived state.
713          * @param \Stock\Entity\Stock $stock
714          * @param string              $previousState
715          */
716         public function directRouteMoveToStock(\Stock\Entity\Stock $stock, $previousState)
717         {
718                 $return_value='This.Stock';
719                 $userId = \Utility\Registry::isAuthenticated()
720                         ? \Utility\Registry::getAuthParam('id')
721                         : 0;
722
723                 if((integer)$previousState!==1)
724                 {
725                         exec("php /var/www/B4C2/public/index.php stock change 1 " . $stock->id . " $userId  > /dev/null &");
726                         //undo relist
727
728                         $query=$this->em->createQuery("UPDATE Auction\Entity\Auction auction SET auction.jobState='' WHERE auction.stock='".$stock->id."' ");
729                         $query->getResult();
730                 }
731
732                 return $return_value;
733
734         }
735
736
737
738         /**
739          * ExecuteAfter: Create.
740          * Push change to mobile devices.
741          * @param array                                 $meta
742          * @param object|null                           $jobRecord
743          * @param object|null                           $record
744          * @param \Workspace\Utility\ServiceInputParams $contract
745          * @return array
746          */
747         public function pushCreateAction($meta, $jobRecord, $record, \Workspace\Utility\ServiceInputParams $contract)
748         {
749                 //-- Pass to backend function so we don't hold up the user response.
750                 $userId = \Utility\Registry::isAuthenticated()
751                         ? \Utility\Registry::getAuthParam('id')
752                         : 0;
753                 exec("php /var/www/B4C2/public/index.php stock change 1 " . $record->id . " $userId  > /dev/null &");
754         }
755
756         /**
757          * ExecuteAfter: Update.
758          * Push change to mobile devices.
759          * @param array                                 $meta
760          * @param object|null                           $jobRecord
761          * @param object|null                           $record
762          * @return array
763          */
764         public function pushUpdateAction($meta, $jobRecord, $record)
765         {
766                 //-- Pass to backend function so we don't hold up the user response.
767                 $userId = \Utility\Registry::isAuthenticated()
768                         ? \Utility\Registry::getAuthParam('id')
769                         : 0;
770                 exec("php /var/www/B4C2/public/index.php stock change 2 " . $record->id . " $userId  > /dev/null &");
771         }
772
773         /**
774          * ExecuteAfter: Delete.
775          * Push change to mobile devices.
776          * @param array                                 $meta
777          * @param object|null                           $jobRecord
778          * @param object|null                           $record
779          * @param \Workspace\Utility\ServiceInputParams $contract
780          * @return array
781          */
782         public function pushDeleteAction($meta, $jobRecord, $record, \Workspace\Utility\ServiceInputParams $contract)
783         {
784                 //-- Pass to backend function so we don't hold up the user response.
785                 $userId = \Utility\Registry::isAuthenticated()
786                         ? \Utility\Registry::getAuthParam('id')
787                         : 0;
788                 exec("php /var/www/B4C2/public/index.php stock change 3 " . $record->id . " $userId  > /dev/null &");
789         }
790
791         /**
792          * Push change notifications for stock item change.
793          * @param $changeCode
794          * @param $id
795          * @param $skipId
796          */
797         public function pushChange($changeCode, $id, $skipId)
798         {
799                 //-- Safety check.
800                 $stock = $this->em->find('Stock\\Entity\\Stock', $id);
801
802                 $minDate = new \DateTime('last month');
803                 if ($minDate->getTimestamp() > $stock->created->getTimestamp()
804                     || 8 == $stock->type->category->id
805                 )
806                 {
807                         //-- Nothing to do, old record.
808                         return;
809                 }
810
811                 //-- Send it to relevant people linked to the company.
812                 $registrations = $this->em->getRepository('Company\\Entity\\DeviceRegistration')
813                         ->findBy(
814                                 array(
815                                         'company' => $stock->company->id
816                                 )
817                         );
818                 $ids           = array();
819                 foreach ($registrations as $registration)
820                 {
821                         if (/*$registration->profile->id != $skipId
822                             && */
823                                 0 < strlen($registration->device->registrationId)
824                         )
825                         {
826                                 $ids[] = $registration->device->registrationId;
827                         }
828                 }
829                 \Utility\Comms\Gcm::send(
830                         $ids,
831                         array(
832                                 'changeCode' => (int)$changeCode,
833                                 'changeId'   => (int)$stock->uvi
834                         )
835                 );
836
837                 //-- Send it to relevant people linked to the trade center.
838                 if ('Trade Center' == $stock->jobState && !is_null($stock->company->tradeCenter))
839                 {
840                         $registrations = $this->em->getRepository('Company\\Entity\\DeviceRegistration')
841                                 ->findBy(
842                                         array(
843                                                 'company' => $stock->company->tradeCenter->id
844                                         )
845                                 );
846                         $ids           = array();
847                         foreach ($registrations as $registration)
848                         {
849                                 if (0 < strlen($registration->device->registrationId)
850                                 )
851                                 {
852                                         $ids[] = $registration->device->registrationId;
853                                 }
854                         }
855                         \Utility\Comms\Gcm::send(
856                                 $ids,
857                                 array(
858                                         'changeCode' => (int)$changeCode,
859                                         'changeId'   => (int)$stock->uvi
860                                 )
861                         );
862                 }
863         }
864
865     /**
866      * CRON functionality: export stock and auction data to file and put it on GEMS ftp server
867      */
868     function exportDataForGems()
869     {
870         \Utility\Debug::errorLog('----------------','Export data for DMD start');
871
872         ini_set('memory_limit','-1');
873
874         /**
875          * @todo
876          * 1. find all users where permission is true = etpGemDmd (exportThirdPartiesGemDmd)
877          * 2. loop through all users to find the company group
878          * 3. run the query to export data to a file
879          * 4. put the exported file on GEM DMD FTP server
880          */
881
882         $inGroupId = array();
883         $fileName = 'gems-export.csv';
884         $filePath = '/tmp/';
885 //        $filePath = '/var/www/NIRPH/Bid4Cars2Repo/data/';
886         $dateAndTime =  new \DateTime("now");
887         $dateAndTime->modify('-7 day');
888 //        $dateAndTime->modify('-500 day');
889         $selectDate = $dateAndTime->format('Y-m-d H:i:s');
890
891 //        \Utility\Debug::errorLog('$selectDate',$selectDate);
892
893
894         $queryResult = $this->em->createQuery(
895             'SELECT profile.id as profileId,company.id as id '
896             . 'FROM \User\Entity\Profile profile '
897             . 'JOIN profile.override override '
898             . 'LEFT JOIN profile.company company '
899 //            . 'LEFT JOIN company.group companyGroup '
900             . 'WHERE override.etpGemDmd = true '
901             . 'AND profile.archived = 0 '
902             . 'AND company.archived = 0 '
903 //            . 'AND companyGroup.archived = 0 '
904             . 'GROUP BY company.id '
905         );
906
907 //        \Utility\Debug::errorLog('$queryResult->getSQL()',$queryResult->getSQL());
908 //        \Utility\Debug::errorLog('$queryResult->getParameters()',$queryResult->getParameters());
909
910         $result = $queryResult->getArrayResult();
911
912
913         for($i = 0; $i <= count($result); $i ++)
914         {
915             if(!empty($result[$i]))
916             {
917                 $inCompanyId[] = $result[$i]['id'];
918             }
919         }
920
921 //        \Utility\Debug::errorLog('$inCompanyId',$inCompanyId);
922
923         if('' != $inCompanyId)
924         {
925             $config = $this->em->getConfiguration();
926             $config->addCustomStringFunction('GROUP_CONCAT', 'UVd\DoctrineFunction\GroupConcat');
927             $config->addCustomStringFunction('DATE_FORMAT', 'UVd\DoctrineFunction\DateFormat');
928             $host = \Utility\Registry::getConfigParam('Host');
929             $exportQuery = $this->em->createQuery(
930                 'SELECT '
931                 . 'DATE_FORMAT(a.endDate ,\'%Y-%m-%d %H:%i:%s\') AS auction_end_date,'
932                 . 'c.name AS company_name, '
933                 . 's.registrationNumber as registration_number, '
934                 . 't.mmCode as mm_code, '
935                 . 's.stockNumber as stock_no, '
936                 . 'xc.name AS colour, '
937                 . 'y.name AS year, '
938                 . 's.km AS mileage, '
939                 . 'DATE_FORMAT(s.created ,\'%Y-%m-%d %H:%i:%s\') AS stock_date,'
940                 . 's.vinNumber as vin_number, '
941                 . 'GROUP_CONCAT(acc.name) AS accessories, '
942                 . 'r.name AS region, '
943                 . 's.tradePrice as trade_price, '
944                 . 's.retailPrice as retail_price, '
945                 . "CONCAT('" . $host . "/img/bin/', mi.filename) as main_image_url, "
946                 . "CONCAT('" . $host . "/img/bin/', fi.filename) as front_image_url, "
947                 . 'condition.name as condition_name, '
948                 . 's.fshNotes as fsh_notes '
949                 . 'FROM \Stock\Entity\Stock s '
950                 . 'JOIN s.auction a '
951                 . 'LEFT JOIN s.mainImage mi '
952                 . 'LEFT JOIN s.frontImage fi '
953                 . 'LEFT JOIN s.company c '
954                 . 'LEFT JOIN s.type t '
955                 . 'LEFT JOIN s.vehicleYear y '
956                 . 'LEFT JOIN s.condition condition '
957                 . 'LEFT JOIN c.city ct '
958                 . 'LEFT JOIN ct.region r '
959                 . 'LEFT JOIN c.group cg '
960                 . 'LEFT JOIN s.exteriorColour xc '
961                 . 'LEFT JOIN s.accessories scc '
962                 . 'LEFT JOIN scc.accessory acc '
963                 . 'WHERE a.endDate > :auctionEndDate '
964                 . 'AND a.jobState = :auctionStatus '
965                 . 'AND c.id IN (:companyId) '
966                 . 'GROUP BY s.id '
967             );
968
969             $exportQuery->setParameter('auctionEndDate', $selectDate);
970             $exportQuery->setParameter('auctionStatus', 'Relist');
971             $exportQuery->setParameter('companyId', $inCompanyId);
972
973 //            \Utility\Debug::errorLog('$exportQuery->getSQL()',$exportQuery->getSQL());
974 //            \Utility\Debug::errorLog('$exportQuery->getParameters()',$exportQuery->getParameters());
975
976             $exportResults = $exportQuery->getArrayResult();
977
978 //            \Utility\Debug::errorLog('count $exportResults',count($exportResults));
979
980             $fp = fopen($filePath.$fileName, 'w');
981
982             fputcsv($fp, array('Auction End Date','Company Name','Registration Number','MM Code','Stock No','Colour','Year','Mileage','Stock Date','Vin Number','Accessories','Region','Trade Price','Retail Price','FSH Notes','Condition','Main Image','Front Image'),';');
983
984
985             foreach($exportResults as $exportResult)
986             {
987                 fputcsv($fp, array($exportResult['auction_end_date'] , $exportResult['company_name'] , $exportResult['registration_number'] , $exportResult['mm_code'] , $exportResult['stock_no'] , $exportResult['colour'] , $exportResult['year'] , $exportResult['mileage'] , $exportResult['stock_date'] , $exportResult['vin_number'] , $exportResult['accessories'] , $exportResult['region'] , $exportResult['trade_price'] , $exportResult['retail_price'] , $exportResult['fsh_notes'] , $exportResult['condition_name'] , $exportResult['main_image_url'] , $exportResult['front_image_url']),';');
988
989             }
990
991             fclose($fp);
992
993             $ftp = new \Utility\Remote\CurlFtpUploader('waws-prod-db3-001.ftp.azurewebsites.windows.net', 'dmd-ftp', 'CQi02Y05ZsiX4NegDf8maMlde0MrefZBdcpzbaTQMtHN5Kp01tCyYiDFk7EP');
994
995             $ftp->setSslVerifyHost(2);
996
997
998             if($ftp->uploadFile($filePath.$fileName,'/uploads/b4c/'.$fileName))
999             {
1000                 \Utility\Debug::errorLog($fileName,"File uploaded");
1001             }
1002             else
1003             {
1004                 \Utility\Debug::errorLog('File could not be uploaded ',$ftp->_errorNo . ' ' . $ftp->_error);
1005             }
1006         }
1007         \Utility\Debug::errorLog('----------------','Export data for DMD end');
1008
1009
1010     }
1011 }
1012
1013
1014