initial commit
[namibia] / module / Workspace / src / Workspace / Controller / DeviceWorkspace2Controller.php
1 <?php
2 namespace Workspace\Controller;
3
4
5 class DeviceWorkspace2Controller extends \Zend\Mvc\Controller\AbstractActionController
6 {
7
8         /**
9          * @var array
10          */
11         protected $request;
12         /**
13          * @var array
14          */
15         protected $requestData;
16         /**
17          * @var array
18          */
19         protected $response;
20         /**
21          * @var \Zend\ServiceManager\ServiceManager
22          */
23         protected $sm;
24         /**
25          * @var \Doctrine\ORM\EntityManager
26          */
27         protected $em;
28         /**
29          * @var string
30          */
31         protected $authToken;
32         /**
33          * @var string
34          */
35         protected $pushKey;
36         /**
37          * @var array
38          */
39         protected $sessionData;
40         /**
41          * @var integer
42          */
43         protected $profileId;
44
45
46
47         /**
48          * Test for sending message to device via GCM.
49          */
50         public function testGcmAction()
51         {
52                 //return;
53                 $result = \Utility\Comms\Gcm::send(
54                         array(
55                                 'd5Io0rJATbY:APA91bF9_h9wmjdxe0PriWZ6DL5EdHOh8_bWdv35mysGDOH-IOUnau_7HhKV8GyTAs4Xe3Vt4vXvM2aC5lhK9pGYy6HaceBbtIsYtn35UN9YQGYaVuWTI9Qvx0ZgK8RksZtJZGYMpege',
56                         ),
57                         array(
58                                 'changeCode' => 1,
59                                 'changeId'   => '1441802190771'
60                         )
61                 );
62                 echo '<pre>';
63                 var_dump($result);
64                 echo '</pre>';
65                 exit();
66         }
67
68
69
70         /**
71          * Initialize.
72          */
73         public function init($arrayDataResponse = false, $expectPost = false)
74         {
75                 //-- Context.
76                 define('APPLICATION', 'Portal');
77                 \Utility\Registry::setServiceManager($this->serviceLocator);
78                 $this->em = \Utility\Registry::getEntityManager();
79                 $this->serviceLocator
80                         ->get('Application')
81                         ->getEventManager()
82                         ->attach(
83                                 \Zend\Mvc\MvcEvent::EVENT_RENDER,
84                                 function ($event)
85                                 {
86                                         $event->getResponse()
87                                                 ->getHeaders()
88                                                 ->addHeaderLine('Content-Type', 'application/json');
89                                 },
90                                 -10000
91                         );
92
93                 //-- Request.
94                 $request           = !$expectPost
95                         ? json_decode(file_get_contents('php://input'), true)
96                         : (isset($_POST['data'])
97                                 ? json_decode($_POST['data'], true)
98                                 : array());
99                 $this->request     = $request;
100                 $this->requestData = is_array($this->request) && array_key_exists('data', $this->request)
101                         ? $this->request['data']
102                         : array();
103                 unset($this->request['data']);
104
105                 //-- Authentication checking.
106                 //   AuthToken check.
107                 if (isset($this->request['authToken']) && !empty($this->request['authToken']))
108                 {
109                         $this->authToken   = $this->request['authToken'];
110                         $this->sessionData = \Utility\Registry::fetchJson('token_' . $this->authToken);
111                         if (is_null($this->sessionData))
112                         {
113                                 //-- Invalid auth token.
114                                 $this->response = new \Zend\View\Model\JsonModel(
115                                         array(
116                                                 'Status' => 'Error',
117                                                 'Reason' => 'Your applications authentication token is not synchronized with the server.'
118                                                             . "\n\n"
119                                                             . 'Please log in again and the data synchronization will continue in the background.',
120                                                 'Data'   => $arrayDataResponse
121                                                         ? array()
122                                                         : new \stdClass()
123                                         )
124                                 );
125                                 return false;
126                         }
127                         \Utility\Registry::set('IsDeviceApiCall', true);
128
129                         //-- Registered device.
130                         $this->profileId = $this->sessionData['AuthData']['id'];
131                 }
132                 //   PushKey check.
133                 if (isset($this->request['pushKey']) && !empty($this->request['pushKey']))
134                 {
135                         $this->pushKey      = $this->request['pushKey'];
136                         $deviceRegistration = $this->em->createQuery(
137                                 'SELECT deviceRegistration '
138                                 . 'FROM Company\Entity\DeviceRegistration deviceRegistration '
139                                 . 'WHERE deviceRegistration.pushKey = :pushKey'
140                         )
141                                 ->setParameter('pushKey', $this->pushKey)
142                                 ->getResult();
143                         if (empty($deviceRegistration))
144                         {
145                                 //-- Unregistered device trying to push data.
146                                 $this->response = new \Zend\View\Model\JsonModel(
147                                         array(
148                                                 'Status' => 'Error',
149                                                 'Reason' => 'Your applications authentication token is not synchronized with the server.'
150                                                             . "\n\n"
151                                                             . 'Please log in again and the data synchronization will continue in the background.',
152                                                 'Data'   => $arrayDataResponse
153                                                         ? array()
154                                                         : new \stdClass()
155                                         )
156                                 );
157                                 return false;
158                         }
159                         \Utility\Registry::set('IsDeviceApiCall', true);
160
161                         //-- Registered device.
162                         $this->profileId = $deviceRegistration[0]->profile->id;
163                 }
164
165                 //-- All good.
166                 return true;
167         }
168
169         /**
170          * Ping-pong.
171          */
172         public function pingAction()
173         {
174                 //-- Fun.
175                 $this->init();
176                 return new \Zend\View\Model\JsonModel(
177                         array(
178                                 'Status' => 'Success',
179                                 'Reason' => 'Awesomeness.',
180                                 'Data'   => array(
181                                         'pong' => true
182                                 )
183                         )
184                 );
185         }
186
187         /**
188          * Register mobile device.
189          * @return \Zend\View\Model\JsonModel
190          */
191         public function registerDeviceAction()
192         {
193                 //-- Preparations.
194                 if (!$this->init())
195                 {
196                         return $this->response;
197                 }
198
199                 //-- Check data packet.
200                 if (!isset($this->requestData['deviceId'])
201                     || !isset($this->requestData['registrationId'])
202                 )
203                 {
204                         return new \Zend\View\Model\JsonModel(
205                                 array(
206                                         'Status' => 'Error',
207                                         'Reason' => 'Require deviceId and registrationId for device registration.',
208                                         'Data'   => new \stdClass()
209                                 )
210                         );
211                 }
212
213                 //-- Do registration.
214                 $device    = $this->em->getRepository('Company\Entity\Device')
215                         ->findOneBy(
216                                 array(
217                                         'deviceId' => $this->requestData['deviceId']
218                                 )
219                         );
220                 $newDevice = is_null($device);
221                 if ($newDevice)
222                 {
223                         $device           = new \Company\Entity\Device();
224                         $device->deviceId = $this->requestData['deviceId'];
225                 }
226                 $device->registrationId = $this->requestData['registrationId'];
227                 if ($newDevice)
228                 {
229                         $this->em->persist($device);
230                 }
231                 $this->em->flush();
232
233                 //-- Done.
234                 return new \Zend\View\Model\JsonModel(
235                         array(
236                                 'Status' => 'Success',
237                                 'Reason' => 'Awesomeness.',
238                                 'Data'   => array(
239                                         'Message' => 'Device registered.'
240                                 )
241                         )
242                 );
243         }
244
245         /**
246          * Device user pin reset.
247          * @return \Zend\View\Model\JsonModel
248          */
249         public function resetPinAction()
250         {
251                 //-- Preparations.
252                 if (!$this->init())
253                 {
254                         return $this->response;
255                 }
256
257                 //-- Check data packet.
258                 $input          = new \Workspace\Utility\ServiceInput('ParamSet', array(
259                         'Login' => array(
260                                 'email'  => isset($this->requestData['email'])
261                                         ? $this->requestData['email']
262                                         : null,
263                                 'mobile' => isset($this->requestData['mobile'])
264                                         ? $this->requestData['mobile']
265                                         : null
266                         )
267                 ));
268                 $serviceInput   = new \Workspace\Utility\ServiceInput('ServiceInput', array(
269                         'data' => $input->pack()
270                 ));
271                 $profileService = $this->serviceLocator->get('User.Service.Profile');
272                 $response       = $profileService->deviceResetPin($serviceInput->pack());
273                 return new \Zend\View\Model\JsonModel(
274                         array(
275                                 'Status' => 'Success',
276                                 'Reason' => 'Awesomeness.',
277                                 'Data'   => $response['Data']
278                         )
279                 );
280         }
281
282         /**
283          * Device user login.
284          * @return \Zend\View\Model\JsonModel
285          */
286         public function loginAction()
287         {
288                 //-- Preparations.
289                 if (!$this->init())
290                 {
291                         return $this->response;
292                 }
293
294                 //-- Check data packet.
295                 if (!isset($this->requestData['deviceId'])
296                     || !isset($this->requestData['email'])
297                     || !isset($this->requestData['pin'])
298                 )
299                 {
300                         return new \Zend\View\Model\JsonModel(
301                                 array(
302                                         'Status' => 'Error',
303                                         'Reason' => 'Require deviceId, email and pin for device login.',
304                                         'Data'   => new \stdClass()
305                                 )
306                         );
307                 }
308
309                 //-- Do authentication.
310                 $input          = new \Workspace\Utility\ServiceInput('ParamSet', array(
311                         'Login' => array(
312                                 'email' => $this->requestData['email'],
313                                 'pin'   => $this->requestData['pin']
314                         )
315                 ));
316                 $serviceInput   = new \Workspace\Utility\ServiceInput('ServiceInput', array(
317                         'data' => $input->pack()
318                 ));
319                 $profileService = $this->serviceLocator->get('User.Service.Profile');
320                 $response       = $profileService->deviceLogin($serviceInput->pack());
321                 if (isset($response['Data']['authToken']))
322                 {
323                         //-- Device entry.
324                         $this->profileId = $response['Data']['id'];
325                         $device          = $this->em->getRepository('Company\Entity\Device')
326                                 ->findOneBy(
327                                         array(
328                                                 'deviceId' => $this->requestData['deviceId']
329                                         )
330                                 );
331                         $newDevice       = is_null($device);
332                         if ($newDevice)
333                         {
334                                 $device           = new \Company\Entity\Device();
335                                 $device->deviceId = $this->requestData['deviceId'];
336                                 if (isset($this->requestData['registrationId']))
337                                 {
338                                         $device->registrationId = $this->requestData['registrationId'];
339                                 }
340                                 $this->em->persist($device);
341                                 $this->em->flush();
342                         }
343
344                         //-- Session data.
345                         $this->authToken   = $response['Data']['authToken'];
346                         $this->sessionData = array(
347                                 'AuthData'  => $response['Data'],
348                                 'AuthToken' => $this->authToken
349                         );
350                         unset($this->sessionData['AuthData']['authToken']);
351                         \Utility\Registry::storeJson('token_' . $this->authToken, $this->sessionData);
352
353                         //-- Device registration.
354                         $dealerId     = $response['Data']['company']['id'];
355                         $registration = $this->em->getRepository('Company\Entity\DeviceRegistration')
356                                 ->findOneBy(
357                                         array(
358                                                 'company' => $dealerId,
359                                                 'device'  => $device->id
360                                         )
361                                 );
362                         if (is_null($registration))
363                         {
364                                 $registration          = new \Company\Entity\DeviceRegistration();
365                                 $registration->company = $this->em->getReference('Company\Entity\Company', $dealerId);
366                                 $registration->profile = $this->em->getReference('User\\Entity\\Profile', $response['Data']['id']);
367                                 $registration->device  = $device;
368                                 $registration->pushKey = md5($device->deviceId . ':' . $dealerId);
369                                 $this->em->persist($registration);
370                                 $this->em->flush();
371                         }
372                         else
373                         {
374                                 $registration->profile = $this->em->getReference('User\\Entity\\Profile', $response['Data']['id']);
375                                 $this->em->flush();
376                         }
377
378                         //-- Response data.
379                         $responseData = array(
380                                 'authToken'          => $this->authToken,
381                                 'pushKey'            => $registration->pushKey,
382                                 'dealerId'           => $dealerId,
383                                 'profileId'          => $response['Data']['id'],
384                                 'fullName'           => $response['Data']['fullName'],
385                                 'permissions'        => array(
386                                         'accessValuations'    => ($response['Data']['permissions']['valuationPage']
387                                                                   && $response['Data']['permissions']['valuationView'])
388                                                                  || $response['Data']['permissions']['valuationCreateSales'],
389                                         'accessVehicles'      => $response['Data']['permissions']['stockPage']
390                                                                  && $response['Data']['permissions']['stockView'],
391                                         'salesValuations'     => $response['Data']['permissions']['valuationCreateSales'],
392                                         'completeValuations'  => $response['Data']['permissions']['valuationCreatePending']
393                                                                  || $response['Data']['permissions']['valuationCreateComplete'],
394                                         'isTradeCenter'       => 'Trade Center' == $response['Data']['company']['dealerType'],
395                                         'linkedToTradeCenter' => isset($response['Data']['company']['tradeCenter']['id'])
396                                 ),
397                                 'valuators'          => array(),
398                                 'allowedAuctionDays' => $this->getAuctionAllowedDays()
399                         );
400                         $profiles     = $this->em->getRepository('User\\Entity\\Profile')
401                                 ->findBy(
402                                         array(
403                                                 'company' => $dealerId
404                                         )
405                                 );
406                         foreach ($profiles as $profile)
407                         {
408                                 if ($profile->override->valuationCreatePending
409                                     || $profile->override->valuationCreateComplete
410                                 )
411                                 {
412                                         $responseData['valuators'][] = array(
413                                                 'id'       => $profile->id,
414                                                 'fullName' => $profile->firstName . ' ' . $profile->familyName
415                                         );
416                                 }
417                         }
418
419                         //-- Done.
420                         return new \Zend\View\Model\JsonModel(
421                                 array(
422                                         'Status' => 'Success',
423                                         'Reason' => 'Awesomeness.',
424                                         'Data'   => $responseData
425                                 )
426                         );
427                 }
428                 else
429                 {
430                         //-- Authentication fail.
431                         return new \Zend\View\Model\JsonModel(
432                                 array(
433                                         'Status' => 'Error',
434                                         'Reason' => 'Authentication failure.',
435                                         'Data'   => new \stdClass()
436                                 )
437                         );
438                 }
439         }
440
441         /**
442          * Retrieve available auction end-date list.
443          * @return \Zend\View\Model\JsonModel
444          */
445         public function getAuctionDaysAction()
446         {
447                 //-- Preparations.
448                 if (!$this->init())
449                 {
450                         return $this->response;
451                 }
452                 $allowed = $this->getAuctionAllowedDays();
453
454
455                 //-- Done.
456                 return new \Zend\View\Model\JsonModel(
457                         array(
458                                 'Status' => 'Success',
459                                 'Reason' => 'Awesomeness.',
460                                 'Data'   => $allowed
461                         )
462                 );
463         }
464
465         protected function canUseAuctionDay($time, array $openDays, array $publicDays)
466         {
467                 if (7 == date('N', $time))
468                 {
469                         return false;
470                 }
471                 if (6 == date('N', $time)
472                     && !in_array(date('Y-m-d', $time), $openDays)
473                 )
474                 {
475                         return false;
476                 }
477                 if (in_array(date('Y-m-d', $time), $publicDays))
478                 {
479                         return false;
480                 }
481                 return true;
482         }
483
484         /**
485          * Retrieve trade and retail from mmCode.
486          * @return \Zend\View\Model\JsonModel
487          */
488         public function transunionFromMmCodeAction()
489         {
490                 //-- Preparations.
491                 if (!$this->init())
492                 {
493                         return $this->response;
494                 }
495
496                 //-- Safety check.
497                 if (!isset($this->requestData['mmCode']) || !is_numeric($this->requestData['mmCode'])
498                     || !isset($this->requestData['vehicleYear']) || !is_numeric($this->requestData['vehicleYear'])
499                 )
500                 {
501                         return new \Zend\View\Model\JsonModel(
502                                 array(
503                                         'Status' => 'Error',
504                                         'Reason' => 'Require mmCode and vehicleYear parameters.',
505                                         'Data'   => new \stdClass()
506                                 )
507                         );
508                 }
509
510                 //-- Process request.
511                 $input            = new \Workspace\Utility\ServiceInput('ParamSet', array(
512                         'Filter' => array(
513                                 'mmCode'      => $this->requestData['mmCode'],
514                                 'vehicleYear' => $this->requestData['vehicleYear'],
515                                 'mileage'     => null,
516                                 'condition'   => null
517                         )
518                 ));
519                 $serviceInput     = new \Workspace\Utility\ServiceInput('ServiceInput', array(
520                         'data' => $input->pack()
521                 ));
522                 $stockUtilService = $this->serviceLocator->get('Stock.Service.Utility');
523                 $response         = $stockUtilService->deviceTransUnionFromMmCode($serviceInput->pack());
524                 if (is_array($response['Data']) && !empty($response['Data'])
525                     && isset($response['Data']['VehicleDetails'])
526                     && !empty($response['Data']['VehicleDetails'])
527                 )
528                 {
529                         return new \Zend\View\Model\JsonModel(
530                                 array(
531                                         'Status' => 'Success',
532                                         'Reason' => 'Awesomeness.',
533                                         'Data'   => array(
534                                                 'NewPrice'    => $response['Data']['VehicleDetails'][0]['Value']['NewPrice'],
535                                                 'RetailPrice' => $response['Data']['VehicleDetails'][0]['Value']['RetailPrice'],
536                                                 'TradePrice'  => $response['Data']['VehicleDetails'][0]['Value']['TradePrice'],
537                                                 'ListPrice'   => $response['Data']['VehicleDetails'][0]['Value']['NewPrice']
538                                         )
539                                 )
540                         );
541                 }
542                 return new \Zend\View\Model\JsonModel(
543                         array(
544                                 'Status' => 'Error',
545                                 'Reason' => 'Could not retrieve trade and retail data.',
546                                 'Data'   => new \stdClass()
547                         )
548                 );
549         }
550
551         /**
552          * Claim a job item from queue.
553          * @return \Zend\View\Model\JsonModel
554          */
555         public function claimJobAction()
556         {
557                 //-- Preparations.
558                 if (!$this->init())
559                 {
560                         return $this->response;
561                 }
562
563                 //-- Safety check.
564                 if (!isset($this->requestData['uvi'])
565                     || 0 >= $this->requestData['uvi']
566                 )
567                 {
568                         return new \Zend\View\Model\JsonModel(
569                                 array(
570                                         'Status' => 'Error',
571                                         'Reason' => 'Require uvi parameter.',
572                                         'Data'   => new \stdClass()
573                                 )
574                         );
575                 }
576                 if (isset($this->requestData['uvi']))
577                 {
578                         $this->requestData['uvi'] = (int) substr($this->requestData['uvi'], 0, 13);
579                 }
580
581                 //-- Attempt to claim the job for this user.
582                 $uvi   = $this->requestData['uvi'];
583                 $stock = $this->em->getRepository('Stock\\Entity\\Stock')
584                         ->findOneBy(array('uvi' => $uvi));
585                 if (is_null($stock) || is_null($stock->valuation))
586                 {
587                         return new \Zend\View\Model\JsonModel(
588                                 array(
589                                         'Status' => 'Error',
590                                         'Reason' => 'Could not find record.',
591                                         'Data'   => new \stdClass()
592                                 )
593                         );
594                 }
595                 $valuation = $stock->valuation;
596                 if (1 != $valuation->queueStatus || !$valuation->claimQueueItem($this->em, $this->profileId))
597                 {
598                         return new \Zend\View\Model\JsonModel(
599                                 array(
600                                         'Status' => 'Error',
601                                         'Reason' => 'Job no longer available.',
602                                         'Data'   => new \stdClass()
603                                 )
604                         );
605                 }
606                 else
607                 {
608                         $recordId = $valuation->id;
609                         $userId   = $this->profileId;
610                         exec("php /var/www/B4C2/public/index.php stock change 4 $recordId $userId  > /dev/null &");
611                         return new \Zend\View\Model\JsonModel(
612                                 array(
613                                         'Status' => 'Success',
614                                         'Reason' => 'Awesomeness.',
615                                         'Data'   => array(
616                                                 'uvi' => $uvi
617                                         )
618                                 )
619                         );
620                 }
621         }
622
623         /**
624          * Claim a job item from queue.
625          * @return \Zend\View\Model\JsonModel
626          */
627         public function unclaimJobAction()
628         {
629                 //-- Preparations.
630                 if (!$this->init())
631                 {
632                         return $this->response;
633                 }
634
635                 //-- Safety check.
636                 if (!isset($this->requestData['uvi'])
637                     || 0 >= $this->requestData['uvi']
638                 )
639                 {
640                         return new \Zend\View\Model\JsonModel(
641                                 array(
642                                         'Status' => 'Error',
643                                         'Reason' => 'Require uvi parameter.',
644                                         'Data'   => new \stdClass()
645                                 )
646                         );
647                 }
648                 if (isset($this->requestData['uvi']))
649                 {
650                         $this->requestData['uvi'] = (int) substr($this->requestData['uvi'], 0, 13);
651                 }
652
653                 //-- Attempt to un-claim this job.
654                 $uvi   = $this->requestData['uvi'];
655                 $stock = $this->em->getRepository('Stock\\Entity\\Stock')
656                         ->findOneBy(array('uvi' => $uvi));
657                 if (is_null($stock) || is_null($stock->valuation))
658                 {
659                         return new \Zend\View\Model\JsonModel(
660                                 array(
661                                         'Status' => 'Error',
662                                         'Reason' => 'Could not find record.',
663                                         'Data'   => new \stdClass()
664                                 )
665                         );
666                 }
667                 $valuation = $stock->valuation;
668                 if (2 != $valuation->queueStatus || !$valuation->unclaimQueueItem($this->em))
669                 {
670                         return new \Zend\View\Model\JsonModel(
671                                 array(
672                                         'Status' => 'Error',
673                                         'Reason' => 'Could not un-claim job.',
674                                         'Data'   => new \stdClass()
675                                 )
676                         );
677                 }
678                 else
679                 {
680                         $recordId = $valuation->id;
681                         $userId   = $this->profileId;
682                         exec("php /var/www/B4C2/public/index.php stock change 5 $recordId $userId  > /dev/null &");
683                         return new \Zend\View\Model\JsonModel(
684                                 array(
685                                         'Status' => 'Success',
686                                         'Reason' => 'Awesomeness.',
687                                         'Data'   => array(
688                                                 'uvi' => $uvi
689                                         )
690                                 )
691                         );
692                 }
693         }
694
695         /**
696          * Get list of valuations.
697          * @return \Zend\View\Model\JsonModel
698          */
699         public function getValuationsAction()
700         {
701                 //-- Preparations.
702                 if (!$this->init())
703                 {
704                         return $this->response;
705                 }
706                 if (is_null($this->sessionData))
707                 {
708                         return new \Zend\View\Model\JsonModel(
709                                 array(
710                                         'Status' => 'Error',
711                                         'Reason' => 'Authentication required.',
712                                         'Data'   => new \stdClass()
713                                 )
714                         );
715                 }
716
717                 //-- Collect valuations.
718                 $minDate = new \DateTime('now');
719                 $minDate->sub(new \DateInterval('P90D'));
720                 $stockItems   = $this->em->createQuery(
721                         'SELECT stock, valuation '
722                         . 'FROM Stock\\Entity\\Stock stock '
723                         . 'JOIN stock.type vehicleType '
724                         . 'JOIN stock.company company '
725                         . 'LEFT JOIN stock.valuation valuation '
726                         . 'WHERE ((IDENTITY(stock.company) = :companyId AND stock.jobState IN (:stockStatusList)) '
727                         . ' OR (IDENTITY(company.tradeCenter) = :companyId AND stock.jobState = :tcStockStatus)) '
728                         . ' AND stock.archived = :archived'
729                         . ' AND IDENTITY(vehicleType.category) < 8'
730                         . ' AND (IDENTITY(stock.valuation) IS NULL OR (valuation.archived = :archived AND valuation.jobState != :statusArchived))'
731                         . ' AND stock.created >= :minDate'
732                 )
733                         ->setParameter('companyId', $this->sessionData['AuthData']['company']['id'])
734                         ->setParameter('archived', 0)
735                         ->setParameter('statusArchived', 'Archived')
736                         ->setParameter('minDate', $minDate)
737                         ->setParameter('stockStatusList', array('Stock', 'Valuation'))
738                         ->setParameter('tcStockStatus', 'Trade Center');
739
740 //        \Utility\Debug::errorLog('getValuationsAction $stockItems->getSQL()', $stockItems->getSQL());
741 //        \Utility\Debug::errorLog('getValuationsAction $stockItems->getParameters()', $stockItems->getParameters());
742
743                 $stockItems = $stockItems->getResult();
744                 $responseData = array();
745                 $i            = 0;
746                 foreach ($stockItems as $stock)
747                 {
748                         //-- Valuation data.
749                         $responseData[$i] = $this->buildValuationData($stock);
750
751                         //-- Done with this valuation.
752                         $i++;
753                 }
754 //\Utility\Debug::errorLog('$responseData', $responseData);
755                 //-- Return to sender.
756                 return new \Zend\View\Model\JsonModel(
757                         array(
758                                 'Status' => 'Success',
759                                 'Reason' => 'Awesomeness.',
760                                 'Data'   => $responseData
761                         )
762                 );
763         }
764
765         /**
766          * Get a specific valuation.
767          * @return \Zend\View\Model\JsonModel
768          */
769         public function getValuationAction()
770         {
771                 //-- Preparations.
772                 if (!$this->init())
773                 {
774                         return $this->response;
775                 }
776                 if (is_null($this->sessionData))
777                 {
778                         return new \Zend\View\Model\JsonModel(
779                                 array(
780                                         'Status' => 'Error',
781                                         'Reason' => 'Authentication required.',
782                                         'Data'   => new \stdClass()
783                                 )
784                         );
785                 }
786                 if (!isset($this->requestData['uvi'])
787                     || !is_numeric($this->requestData['uvi'])
788                 )
789                 {
790                         return new \Zend\View\Model\JsonModel(
791                                 array(
792                                         'Status' => 'Error',
793                                         'Reason' => 'Field uvi required.',
794                                         'Data'   => new \stdClass()
795                                 )
796                         );
797                 }
798                 if (isset($this->requestData['uvi']))
799                 {
800                         $this->requestData['uvi'] = (int) substr($this->requestData['uvi'], 0, 13);
801                 }
802
803                 //-- Collect valuations.
804                 $stock = $this->em->getRepository('Stock\\Entity\\Stock')
805                         ->findOneBy(
806                                 array(
807                                         'uvi' => $this->requestData['uvi']
808                                 )
809                         );
810                 if (is_null($stock))
811                 {
812                         //-- Oops, 404.
813                         return new \Zend\View\Model\JsonModel(
814                                 array(
815                                         'Status' => 'Error',
816                                         'Reason' => 'Stock entry not found.',
817                                         'Data'   => new \stdClass()
818                                 )
819                         );
820                 }
821                 else
822                 {
823                         //-- All good.
824                         return new \Zend\View\Model\JsonModel(
825                                 array(
826                                         'Status' => 'Success',
827                                         'Reason' => 'Awesomeness.',
828                                         'Data'   => $this->buildValuationData($stock)
829                                 )
830                         );
831                 }
832         }
833
834         /**
835          * Synchronize multiple valuations.
836          * @return \Zend\View\Model\JsonModel
837          */
838         public function synchValuationsAction()
839         {
840                 //-- Preparations.
841                 if (!$this->init(true))
842                 {
843                         return $this->response;
844                 };
845                 \Utility\Registry::set('IsDeviceApiCall', true);
846
847
848                 //-- Loop through valuations.
849                 $response = array();
850                 foreach ($this->requestData as $valuationItem)
851                 {
852                         //-- Safety checks.
853                         $uviii = isset($valuationItem['uvi'])
854                                 ? $valuationItem['uvi']
855                                 : 'null';
856                         if (!isset($valuationItem['dealerId'])
857                             || !is_numeric($valuationItem['dealerId'])
858                         )
859                         {
860                                 error_log("synchValuationsAction : $uviii : NO DEALER ID");
861                                 $response[] = array(
862                                         'error' => 'Field dealerId required.'
863                                 );
864                                 continue;
865                         }
866                         if (!isset($valuationItem['profileId'])
867                             || !is_numeric($valuationItem['profileId'])
868                         )
869                         {
870                                 error_log("synchValuationsAction : $uviii : NO PROFILE ID");
871                                 $response[] = array(
872                                         'error' => 'Field profileId required.'
873                                 );
874                                 continue;
875                         }
876                         if (!isset($valuationItem['owner'])
877                             || 0 == strlen($valuationItem['owner'])
878                         )
879                         {
880                                 error_log("synchValuationsAction : $uviii : NO OWNER");
881                                 $response[] = array(
882                                         'error' => 'Field owner required.'
883                                 );
884                                 continue;
885                         }
886                         if (!isset($valuationItem['status'])
887                             || 0 == strlen($valuationItem['status'])
888                         )
889                         {
890                                 error_log("synchValuationsAction : $uviii : NO STATUS");
891                                 $response[] = array(
892                                         'error' => 'Field status required.'
893                                 );
894                                 continue;
895                         }
896
897                         //-- Establish context.
898                         $originalUvi = null;
899                         if (isset($valuationItem['uvi']))
900                         {
901                                 $originalUvi          = $valuationItem['uvi'];
902                                 $valuationItem['uvi'] = (int) substr($valuationItem['uvi'], 0, 13);
903                         }
904                         $uviii = $valuationItem['uvi'];
905                         error_log("synchValuationsAction : $originalUvi : $uviii");
906                         $userId       = $valuationItem['profileId'];
907                         $dealerId     = $valuationItem['dealerId'];
908                         $existingItem = isset($valuationItem['uvi']);
909                         $owner        = $valuationItem['owner'];
910                         if (0 == $dealerId || 0 == $userId)
911                         {
912                                 $userId = $this->profileId;
913                                 if (!is_null($userId) && false != $userId && is_numeric($userId))
914                                 {
915                                         $profile  = $this->em->find('User\\Entity\\Profile', $userId);
916                                         $dealerId = $profile->company->id;
917                                 }
918                         }
919                         if ($existingItem)
920                         {
921                                 $stock        = $this->em->getRepository('Stock\\Entity\\Stock')
922                                         ->findOneBy(
923                                                 array(
924                                                         'uvi' => $valuationItem['uvi']
925                                                 )
926                                         );
927                                 $existingItem = !is_null($stock);
928                         }
929                         $valuation = null;
930                         if ($existingItem)
931                         {
932                                 $changeCode   = 2;
933                                 $valuation    = $stock->valuation;
934                                 $initialState = 'Valuation' == $owner
935                                         ? $valuation->jobState
936                                         : $stock->jobState;
937                         }
938                         else
939                         {
940                                 $changeCode = 1;
941                                 $stock      = new \Stock\Entity\Stock();
942                                 if (isset($valuationItem['uvi'])
943                                     && !is_null($valuationItem['uvi'])
944                                     && 0 < strlen($valuationItem['uvi'])
945                                 )
946                                 {
947                                         $stock->uvi = $valuationItem['uvi'];
948                                 }
949                                 $stock->createdBy = $this->em->getReference('User\\Entity\\Profile', $userId);
950                                 $stock->company   = $this->em->getReference('Company\\Entity\\Company', $dealerId);
951                                 $this->em->persist($stock);
952                                 if ('Valuation' == $owner)
953                                 {
954                                         $valuation            = new \Valuation\Entity\Valuation();
955                                         $valuation->stock     = $stock;
956                                         $valuation->createdBy = $this->em->getReference('User\\Entity\\Profile', $userId);
957                                         $this->em->persist($valuation);
958                                 }
959                         }
960
961                         //-- Collect stock data.
962                         $stock->type      = $this->em->getReference(
963                                 'Stock\\Entity\\Type',
964                                 $valuationItem['vehicleModelTypeId']
965                         );
966                         $stock->createdBy = $this->em->getReference('User\\Entity\\Profile', $userId);
967                         $stock->company   = $this->em->getReference('Company\\Entity\\Company', $dealerId);
968                         //\Utility\Debug::errorLog('$valuationItem', $valuationItem);
969                         if (isset($valuationItem['stockNumber']) && 0 < strlen($valuationItem['stockNumber']))
970                         {
971                                 $stock->stockNumber = $valuationItem['stockNumber'];
972                         }
973                         if (isset($valuationItem['licenceNumber']))
974                         {
975                                 $stock->registrationNumber = $valuationItem['licenceNumber'];
976                         }
977                         if (isset($valuationItem['vinNumber']))
978                         {
979                                 $stock->vinNumber = $valuationItem['vinNumber'];
980                         }
981                         if (isset($valuationItem['engineNumber']))
982                         {
983                                 $stock->engineNumber = $valuationItem['engineNumber'];
984                         }
985                         if (isset($valuationItem['fuelTypeId'])
986                             && 0 < $valuationItem['fuelTypeId']
987                         )
988                         {
989                                 $stock->fuelType = $this->em->getReference(
990                                         'Stock\\Entity\\FuelType',
991                                         $valuationItem['fuelTypeId']
992                                 );
993                         }
994                         if (isset($valuationItem['transmissionTypeId'])
995                             && 0 < $valuationItem['transmissionTypeId']
996                         )
997                         {
998                                 $stock->transmissionType = $this->em->getReference(
999                                         'Stock\\Entity\\TransmissionType',
1000                                         $valuationItem['transmissionTypeId']
1001                                 );
1002                         }
1003                         if (isset($valuationItem['exteriorColourId'])
1004                             && 0 < $valuationItem['exteriorColourId']
1005                         )
1006                         {
1007                                 $stock->exteriorColour = $this->em->getReference(
1008                                         'Stock\\Entity\\ExteriorColour',
1009                                         $valuationItem['exteriorColourId']
1010                                 );
1011                         }
1012                         if (isset($valuationItem['interiorColourId'])
1013                             && 0 < $valuationItem['interiorColourId']
1014                         )
1015                         {
1016                                 $stock->interiorColour = $this->em->getReference(
1017                                         'Stock\\Entity\\InteriorColour',
1018                                         $valuationItem['interiorColourId']
1019                                 );
1020                         }
1021                         if (isset($valuationItem['vehicleConditionId'])
1022                             && 0 < $valuationItem['vehicleConditionId']
1023                         )
1024                         {
1025                                 $stock->condition = $this->em->getReference(
1026                                         'Stock\\Entity\\Condition',
1027                                         $valuationItem['vehicleConditionId']
1028                                 );
1029                         }
1030                         if (isset($valuationItem['vehicleYearId'])
1031                             && 0 < $valuationItem['vehicleYearId']
1032                         )
1033                         {
1034                                 $stock->vehicleYear = $this->em->getReference(
1035                                         'Stock\\Entity\\Year',
1036                                         $valuationItem['vehicleYearId']
1037                                 );
1038                         }
1039                         if (isset($valuationItem['vehicleMileage']))
1040                         {
1041                                 $stock->km = $valuationItem['vehicleMileage'];
1042                         }
1043                         if (isset($valuationItem['upholsteryId'])
1044                             && 0 < $valuationItem['upholsteryId']
1045                         )
1046                         {
1047                                 $stock->upholstery = $this->em->getReference(
1048                                         'Stock\\Entity\\Upholstery',
1049                                         $valuationItem['upholsteryId']
1050                                 );
1051                         }
1052                         if (isset($valuationItem['spareKeysId'])
1053                             && 0 < $valuationItem['spareKeysId']
1054                         )
1055                         {
1056                                 $stock->spareKeys = $valuationItem['spareKeysId'];
1057                         }
1058                         if (isset($valuationItem['fullServiceHistoryId'])
1059                             && 0 < $valuationItem['fullServiceHistoryId']
1060                         )
1061                         {
1062                                 $stock->fullServiceHistory = $this->em->getReference(
1063                                         'Stock\\Entity\\FullServiceHistory',
1064                                         $valuationItem['fullServiceHistoryId']
1065                                 );
1066                         }
1067                         if (isset($valuationItem['fullServiceHistoryNotes']))
1068                         {
1069                                 $stock->fshNotes = $valuationItem['fullServiceHistoryNotes'];
1070                         }
1071                         if (isset($valuationItem['tradePrice']))
1072                         {
1073                                 $stock->tradePrice = $valuationItem['tradePrice'];
1074                         }
1075                         if (isset($valuationItem['retailPrice']))
1076                         {
1077                                 $stock->retailPrice = $valuationItem['retailPrice'];
1078                         }
1079                         if (isset($valuationItem['listPrice']))
1080                         {
1081                                 $stock->listPrice = $valuationItem['listPrice'];
1082                         }
1083                         if ($existingItem)
1084                         {
1085                                 foreach ($stock->accessories as $accessory)
1086                                 {
1087                                         $this->em->remove($accessory);
1088                                 }
1089                                 foreach ($stock->damages as $damage)
1090                                 {
1091                                         $this->em->remove($damage);
1092                                 }
1093
1094                                 $this->em->flush();
1095                         }
1096                         if (isset($valuationItem['accessories'])
1097                             && 0 < strlen($valuationItem['accessories'])
1098                         )
1099                         {
1100                                 $idList = explode(':', $valuationItem['accessories']);
1101                                 foreach ($idList as $accessoryId)
1102                                 {
1103                                         $stockAccessory            = new \Stock\Entity\StockAccessory();
1104                                         $stockAccessory->stock     = $stock;
1105                                         $stockAccessory->accessory = $this->em->getReference(
1106                                                 'Stock\\Entity\\Accessory',
1107                                                 $accessoryId
1108                                         );
1109                                         $this->em->persist($stockAccessory);
1110                                 }
1111                         }
1112                         if (isset($valuationItem['accessoriesComments']))
1113                         {
1114                                 $stock->accessoryNotes = $valuationItem['accessoriesComments'];
1115                         }
1116                         $damageTotal = 0.0;
1117                         if (isset($valuationItem['damages']))
1118                         {
1119                                 if (!is_array($valuationItem['damages']))
1120                                 {
1121                                         $valuationItem['damages'] = json_decode($valuationItem['damages'], true);
1122                                 }
1123                                 if (0 < count($valuationItem['damages']))
1124                                 {
1125                                         foreach ($valuationItem['damages'] as $damageItem)
1126                                         {
1127                                                 if ((float)$damageItem['amount'] == 0.0)
1128                                                 {
1129                                                         continue;
1130                                                 }
1131                                                 $damage         = new \Stock\Entity\StockDamage();
1132                                                 $damage->stock  = $stock;
1133                                                 $damage->damage = $this->em->getReference(
1134                                                         'Stock\\Entity\\Damage',
1135                                                         $damageItem['serverId']
1136                                                 );
1137                                                 $damage->amount = $damageItem['amount'];
1138                                                 $this->em->persist($damage);
1139
1140                                                 $damageTotal += (float)$damageItem['amount'];
1141                                         }
1142                                 }
1143                         }
1144                         if (isset($valuationItem['damagesEstimatedRepairCost']))
1145                         {
1146                                 $stock->damageTotal = $damageTotal;
1147                         }
1148                         if (isset($valuationItem['damagesComments']))
1149                         {
1150                                 $stock->damageNotes = $valuationItem['damagesComments'];
1151                         }
1152                         if (isset($valuationItem['damagesPreviousRepairsNoted']))
1153                         {
1154                                 $stock->previousRepairsNoted = $valuationItem['damagesPreviousRepairsNoted'];
1155                         }
1156                         if (isset($valuationItem['damagesPreviousRepairsComments']))
1157                         {
1158                                 $stock->previousRepairsNotes = $valuationItem['damagesPreviousRepairsComments'];
1159                         }
1160
1161                         //-- Valuation data.
1162                         if ('Valuation' == $owner)
1163                         {
1164                                 $valuation->createdBy = $this->em->getReference('User\\Entity\\Profile', $userId);
1165                                 if (isset($valuationItem['customerName']))
1166                                 {
1167                                         $valuation->firstName = $valuationItem['customerName'];
1168                                 }
1169                                 if (isset($valuationItem['customerSurname']))
1170                                 {
1171                                         $valuation->familyName = $valuationItem['customerSurname'];
1172                                 }
1173                                 if (isset($valuationItem['customerCellNumber']))
1174                                 {
1175                                         $valuation->mobile = $valuationItem['customerCellNumber'];
1176                                 }
1177                                 if (isset($valuationItem['offer']) && 0 < $valuationItem['offer'])
1178                                 {
1179                                         $valuation->amountOffered = $valuationItem['offer'];
1180                                 }
1181                         }
1182
1183                         //-- Status.
1184                         if ('Valuation' == $owner)
1185                         {
1186                                 $stock->jobState     = 'Valuation';
1187                                 $valuation->jobState = $valuationItem['status'];
1188                                 if (isset($valuationItem['previousStatus']) && '' != $valuationItem['previousStatus'])
1189                                 {
1190                                         $valuation->previousState = $valuationItem['previousStatus'];
1191                                 }
1192                         }
1193                         else
1194                         {
1195                                 if (!is_null($valuation))
1196                                 {
1197                                         $valuation->previousState = $valuation->jobState;
1198                                         $valuation->jobState      = 'Stock';
1199                                         $this->em->flush($valuation);
1200                                 }
1201                                 $stock->jobState = $valuationItem['status'];
1202                                 if (isset($valuationItem['previousStatus']) && '' != $valuationItem['previousStatus'])
1203                                 {
1204                                         $stock->previousState = $valuationItem['previousStatus'];
1205                                 }
1206                         }
1207
1208
1209                         //-- Flush data.
1210                         try
1211                         {
1212                                 $this->em->flush($stock);
1213                                 $stock->postInsert();
1214                                 if ('Valuation' == $owner)
1215                                 {
1216                                         $this->em->flush($valuation);
1217                                 }
1218                                 $stock->valuation = $valuation;
1219                                 $this->em->flush();
1220                                 $response[] = array(
1221                                         'modifiedUvi' => (int) substr($stock->uvi, 0, 13),
1222                                         'uvi'         => $originalUvi
1223                                 );
1224                         }
1225                         catch (\Exception $e)
1226                         {
1227                                 if (1452517638893 == $originalUvi)
1228                                 {
1229                                         $response[] = array(
1230                                                 'modifiedUvi' => (int) $originalUvi,
1231                                                 'uvi'         => $originalUvi
1232                                         );
1233                                 }
1234                                 else
1235                                 {
1236                                         \Utility\Debug::errorLog(__METHOD__ . ':SynchValuationError on dealer:user', "$dealerId : $userId on $originalUvi");
1237                                         \Utility\Debug::errorLog(__METHOD__ . ':$valuationItem', $valuationItem);
1238                                         \Utility\Debug::errorLog(__METHOD__ . ':EXCEPTION', $e->getMessage());
1239                                         \Utility\Debug::errorLog(__METHOD__ . ':TRACE', $e->getTraceAsString());
1240                                         $response[] = array(
1241                                                 'error' => 'Could not create entry.'
1242                                         );
1243                                 }
1244                                 continue;
1245                         }
1246
1247             \Utility\Debug::errorLog('$initialState', $initialState);
1248             \Utility\Debug::errorLog('$valuationItem[status]', $valuationItem['status']);
1249
1250                         //-- Actions to apply.
1251                         if (!$existingItem
1252                             || $initialState != $valuationItem['status']
1253                         )
1254                         {
1255                                 if ('Valuation' == $owner)
1256                                 {
1257
1258                                         error_log("synchValuationsAction : $originalUvi " . print_r($valuationItem, true));
1259
1260                                         if ('New Valuation' == $valuation->jobState
1261                                             && 0 < $valuationItem['valuator']
1262                                         )
1263                                         {
1264                                                 //-- Send to valuator.
1265                                                 if (!$this->sendToValuator($valuationItem, $valuation))
1266                                                 {
1267                                                         //-- Failed sending to Valuator.
1268                                                         $this->em->flush();
1269                                                 }
1270                                         }
1271                                         if ('Price Guide' == $valuation->jobState)
1272                                         {
1273                                                 //-- Attempt sending to Price Guide.
1274                                                 if (!$this->sendValuationToPriceGuide($valuationItem, $valuation))
1275                                                 {
1276                                                         //-- Failed sending to Price Guide.
1277                                                         $valuation->jobState = 'Pending Valuation';
1278                                                         $this->em->flush();
1279                                                 }
1280                                         }
1281                                 }
1282                                 else
1283                                 {
1284                     \Utility\Debug::errorLog('in else', $stock->jobState);
1285
1286                                         if ('Auction' == $stock->jobState)
1287                                         {
1288                                                 //-- Attempt sending to auction.
1289                                                 if (!$this->sendToAuction($valuationItem, $stock))
1290                                                 {
1291                                                         //-- Failed sending to Valuator.
1292                                                         $this->em->flush();
1293                                                 }
1294                                         }
1295                                         if ('Price Guide' == $stock->jobState)
1296                                         {
1297                                                 //-- Attempt sending to Price Guide.
1298                                                 if (!$this->sendStockToPriceGuide($valuationItem, $stock))
1299                                                 {
1300                                                         //-- Failed sending to Price Guide.
1301                                                         $stock->jobState = 'Stock';
1302                                                         $this->em->flush();
1303                                                 }
1304                                         }
1305                                         if ('Trade Center' == $stock->jobState)
1306                                         {
1307                                                 //-- Attempt sending to Trade Center.
1308                                                 $stock->jobState = 'Stock';
1309                                                 $this->em->flush();
1310                                                 if (!$this->sendStockToTradeCenter($valuationItem, $stock))
1311                                                 {
1312                                                         //-- Failed sending to Price Guide.
1313                                                         $stock->jobState = 'Stock';
1314                                                         $this->em->flush();
1315                                                 }
1316                                         }
1317                                 }
1318                         }
1319
1320                         //-- Change notification.
1321                         $owner    = 'Valuation' == $owner
1322                                 ? 'valuation'
1323                                 : 'stock';
1324                         $recordId = 'Valuation' == $owner
1325                                 ? $valuation->id
1326                                 : $stock->id;
1327                         exec("php /var/www/B4C2/public/index.php stock change $changeCode $recordId $userId  > /dev/null &");
1328
1329                         error_log("synchValuationsAction : $originalUvi : \\o/");
1330                 }
1331
1332         \Utility\Debug::errorLog('\Zend\View\Model\JsonModel', array(
1333             'Status' => 'Success',
1334             'Reason' => 'Awesomeness.',
1335             'Data'   => $response
1336         ));
1337
1338                 //-- Return to sender.
1339                 return new \Zend\View\Model\JsonModel(
1340                         array(
1341                                 'Status' => 'Success',
1342                                 'Reason' => 'Awesomeness.',
1343                                 'Data'   => $response
1344                         )
1345                 );
1346         }
1347
1348         /**
1349          * Synchronize multiple photos.
1350          * @return \Zend\View\Model\JsonModel
1351          */
1352         public function synchPhotosAction()
1353         {
1354                 //-- Preparations.
1355                 if (!$this->init(true, true))
1356                 {
1357                         return $this->response;
1358                 }
1359
1360                 //-- Loop through valuations.
1361                 $filePath  = \Utility\Registry::getConfigParam('ImagePath');
1362                 $thumbPath = \Utility\Registry::getConfigParam('ThumbnailPath');
1363
1364                 //-- Safety checks.
1365                 if (!isset($this->requestData['uvi'])
1366                     || !is_numeric($this->requestData['uvi'])
1367                 )
1368                 {
1369                         error_log("synchPhotosAction : NON NUMERIC UVI : " . (!isset($this->requestData['uvi']) ? 'NO UVI' : $this->requestData['uvi']));
1370                         return new \Zend\View\Model\JsonModel(
1371                                 array(
1372                                         'Status' => 'Error',
1373                                         'Reason' => 'Field uvi required.',
1374                                         'Data'   => new \stdClass()
1375                                 )
1376                         );
1377                 }
1378                 if (!isset($this->requestData['type'])
1379                     || empty($this->requestData['type'])
1380                 )
1381                 {
1382                         error_log("synchPhotosAction : FIELD TYPE REQUIRED : ");
1383                         return new \Zend\View\Model\JsonModel(
1384                                 array(
1385                                         'Status' => 'Error',
1386                                         'Reason' => 'Field type required.',
1387                                         'Data'   => new \stdClass()
1388                                 )
1389                         );
1390                 }
1391                 $originalUvi = null;
1392                 if (isset($this->requestData['uvi']))
1393                 {
1394                         $originalUvi              = $this->requestData['uvi'];
1395                         $this->requestData['uvi'] = (int) substr($this->requestData['uvi'], 0, 13);
1396                 }
1397                 error_log("synchPhotosAction : $originalUvi >> " . $this->requestData['uvi']);
1398
1399                 //-- Get stock item.
1400                 $uvi         = $this->requestData['uvi'];
1401                 $type        = $this->requestData['type'];
1402                 $newFileName = $filePath . $type . $uvi . '.jpg';
1403                 $stock       = $this->em
1404                         ->getRepository('Stock\\Entity\\Stock')
1405                         ->findOneBy(array('uvi' => $this->requestData['uvi']));
1406                 if (is_null($stock))
1407                 {
1408                         error_log("synchPhotosAction : $originalUvi >> COULD NOT FIND STOCK ENTRY");
1409                         return new \Zend\View\Model\JsonModel(
1410                                 array(
1411                                         'Status' => 'Error',
1412                                         'Reason' => 'Could not find stock entry.',
1413                                         'Data'   => new \stdClass()
1414                                 )
1415                         );
1416                 }
1417
1418                 //-- Save the image.
1419                 ini_set('memory_limit', '512M');
1420                 if (!move_uploaded_file($_FILES['photo']['tmp_name'], $newFileName)
1421                         || !file_exists($newFileName))
1422                 {
1423                         error_log("synchPhotosAction : $originalUvi >> COULD NOT MOVE TEMP FILE");
1424                         return new \Zend\View\Model\JsonModel(
1425                                 array(
1426                                         'Status' => 'Error',
1427                                         'Reason' => 'Could not move temp file.',
1428                                         'Data'   => new \stdClass()
1429                                 )
1430                         );
1431                 }
1432                 $photo = file_get_contents($newFileName, FILE_BINARY);
1433                 $this->resizeImage($photo, 'image/jpeg', $thumbPath . $type . $uvi . '.jpg');
1434                 $image           = new \Utility\Entity\Image();
1435                 $image->filename = $type . $uvi . '.jpg';
1436                 $image->mimeType = 'image/jpeg';
1437                 $this->em->persist($image);
1438                 $this->em->flush();
1439
1440                 //-- Update stock entry.
1441                 switch (strtoupper($type))
1442                 {
1443                         case 'MAIN':
1444                                 $stock->mainImage = $image;
1445                                 break;
1446                         case 'FRONT':
1447                                 $stock->frontImage = $image;
1448                                 break;
1449                         case 'RIGHT':
1450                                 $stock->rightImage = $image;
1451                                 break;
1452                         case 'LEFT':
1453                                 $stock->leftImage = $image;
1454                                 break;
1455                         case 'BACK':
1456                                 $stock->backImage = $image;
1457                                 break;
1458                         case 'ENGINE':
1459                                 $stock->engineImage = $image;
1460                                 break;
1461                         case 'INTERIOR':
1462                                 $stock->interiorImage = $image;
1463                                 break;
1464                         case 'NATIS':
1465                                 $stock->natisImage = $image;
1466                                 break;
1467                 }
1468                 $this->em->flush();
1469                 $response = array(
1470                         'modifiedUvi' => $uvi,
1471                         'uvi'         => $originalUvi,
1472                         'type'        => $type
1473                 );
1474                 exec("php /var/www/B4C2/public/index.php stock change 2 " . $stock->id . " 0  > /dev/null &");
1475
1476                 //-- Return to sender.
1477                 error_log("synchPhotosAction : " . print_r($response, true));
1478                 error_log("synchPhotosAction : $originalUvi >> \\o/");
1479                 return new \Zend\View\Model\JsonModel(
1480                         array(
1481                                 'Status' => 'Success',
1482                                 'Reason' => 'Awesomeness.',
1483                                 'Data'   => $response
1484                         )
1485                 );
1486         }
1487
1488         /**
1489          * Get up to date with latest data.
1490          * @return \Zend\View\Model\JsonModel
1491          */
1492         public function getMakesAction()
1493         {
1494                 //-- Preparations.
1495                 if (!$this->init())
1496                 {
1497                         return $this->response;
1498                 }
1499
1500                 //-- Let the utility handle it.
1501                 $this->requestData['datasetName'] = 'makes';
1502                 return $this->getDataUpdatesAction();
1503         }
1504
1505         /**
1506          * Get up to date with latest data.
1507          * @return \Zend\View\Model\JsonModel
1508          */
1509         public function getModelsAction()
1510         {
1511                 //-- Preparations.
1512                 if (!$this->init())
1513                 {
1514                         return $this->response;
1515                 }
1516
1517                 //-- Let the utility handle it.
1518                 $this->requestData['datasetName'] = 'models';
1519                 return $this->getDataUpdatesAction();
1520         }
1521
1522         /**
1523          * Get up to date with latest data.
1524          * @return \Zend\View\Model\JsonModel
1525          */
1526         public function getTypesAction()
1527         {
1528                 //-- Preparations.
1529                 if (!$this->init())
1530                 {
1531                         return $this->response;
1532                 }
1533
1534                 //-- Let the utility handle it.
1535                 $this->requestData['datasetName'] = 'types';
1536                 return $this->getDataUpdatesAction();
1537         }
1538
1539         /**
1540          * Get up to date with latest data.
1541          * @return \Zend\View\Model\JsonModel
1542          */
1543         public function getYearsAction()
1544         {
1545                 //-- Preparations.
1546                 if (!$this->init())
1547                 {
1548                         return $this->response;
1549                 }
1550
1551                 //-- Let the utility handle it.
1552                 $this->requestData['datasetName'] = 'years';
1553                 return $this->getDataUpdatesAction();
1554         }
1555
1556         /**
1557          * Get up to date with latest data.
1558          * @return \Zend\View\Model\JsonModel
1559          */
1560         public function getAccessoriesAction()
1561         {
1562                 //-- Preparations.
1563                 if (!$this->init())
1564                 {
1565                         return $this->response;
1566                 }
1567
1568                 //-- Let the utility handle it.
1569                 $this->requestData['datasetName'] = 'accessories';
1570                 return $this->getDataUpdatesAction();
1571         }
1572
1573         /**
1574          * Get up to date with latest data.
1575          * @return \Zend\View\Model\JsonModel
1576          */
1577         protected function getDataUpdatesAction()
1578         {
1579                 //-- Safety checks.
1580                 if (!isset($this->requestData['datasetName'])
1581                     || 0 == strlen($this->requestData['datasetName'])
1582                 )
1583                 {
1584                         return new \Zend\View\Model\JsonModel(
1585                                 array(
1586                                         'Status' => 'Error',
1587                                         'Reason' => 'Field datasetName required.',
1588                                         'Data'   => new \stdClass()
1589                                 )
1590                         );
1591                 }
1592
1593                 //-- Context.
1594                 switch ($this->requestData['datasetName'])
1595                 {
1596                         #-> Location
1597                         case 'countries':
1598                                 $entityName = '\Location\Entity\Country';
1599                                 break;
1600                         case 'regions':
1601                                 $entityName = '\Location\Entity\Region';
1602                                 break;
1603                         case 'towns':
1604                                 $entityName = '\Location\Entity\Town';
1605                                 break;
1606                         #-> Stock
1607                         case 'valuations':
1608                                 $entityName = '\Valuation\Entity\Valuation';
1609                                 break;
1610                         case 'accessories':
1611                                 $entityName = '\Stock\Entity\Accessory';
1612                                 break;
1613                         case 'damages':
1614                                 $entityName = '\Stock\Entity\Damage';
1615                                 break;
1616                         case 'upholstery':
1617                                 $entityName = '\Stock\Entity\Upholstery';
1618                                 break;
1619                         case 'condition':
1620                                 $entityName = '\Stock\Entity\Condition';
1621                                 break;
1622                         case 'exteriorColours':
1623                                 $entityName = '\Stock\Entity\ExteriorColour';
1624                                 break;
1625                         case 'interiorColours':
1626                                 $entityName = '\Stock\Entity\InteriorColour';
1627                                 break;
1628                         case 'fuelTypes':
1629                                 $entityName = '\Stock\Entity\FuelType';
1630                                 break;
1631                         case 'fullServiceHistory':
1632                                 $entityName = '\Stock\Entity\FullServiceHistory';
1633                                 break;
1634                         case 'transmissionTypes':
1635                                 $entityName = '\Stock\Entity\TransmissionType';
1636                                 break;
1637                         case 'natis':
1638                                 $entityName = '\Stock\Entity\Natis';
1639                                 break;
1640                         case 'papers':
1641                                 $entityName = '\Stock\Entity\Paper';
1642                                 break;
1643                         case 'years':
1644                                 $entityName = '\Stock\Entity\Year';
1645                                 break;
1646                         case 'categories':
1647                                 $entityName = '\Stock\Entity\Category';
1648                                 break;
1649                         case 'makes':
1650                                 $entityName = '\Stock\Entity\Make';
1651                                 break;
1652                         case 'models':
1653                                 ini_set('memory_limit', '512M');
1654                                 $entityName = '\Stock\Entity\Model';
1655                                 break;
1656                         case 'types':
1657                                 ini_set('memory_limit', '1024M');
1658                                 $entityName = '\Stock\Entity\Type';
1659                                 break;
1660                         default:
1661                                 return new \Zend\View\Model\JsonModel(
1662                                         array(
1663                                                 'Status' => 'Error',
1664                                                 'Reason' => 'Invalid datasetName ' . $this->requestData['datasetName'] . ' requested.',
1665                                                 'Data'   => new \stdClass()
1666                                         )
1667                                 );
1668                                 break;
1669                 }
1670
1671                 //-- Collect relevant data.
1672                 $responseData = array();
1673                 $version      = isset($this->requestData['version'])
1674                                 && is_numeric($this->requestData['version'])
1675                         ? $this->requestData['version']
1676                         : 0;
1677                 $maxVersion   = $version;
1678                 $version++;
1679                 if ('Build' == $entityName::PULL_SYNCH_STRATEGY)
1680                 {
1681                         $filter = 'WHERE 1=1';
1682                         $filter .= defined($entityName . '::JOB_QUEUE')
1683                                 ? ' AND a.queueStatus = 1'
1684                                 : '';
1685                         $filter .= $entityName::ARCHIVE
1686                                 ? ' AND a.archived = 0'
1687                                 : '';
1688                         if (method_exists($entityName, 'getSynchQuery'))
1689                         {
1690                                 $query = $this->em->createQuery(
1691                                         $entityName::getSynchQuery()
1692                                 );
1693                         }
1694                         else
1695                         {
1696                                 $query = $this->em->createQuery(
1697                                         "SELECT a FROM $entityName a $filter ORDER BY a.id ASC"
1698                                 );
1699                         }
1700                         $responseData = $query->getResult();
1701                         if (defined($entityName . '::JOB_QUEUE'))
1702                         {
1703                                 foreach ($responseData as $rowId => $record)
1704                                 {
1705                                         $responseData[$rowId] = $record->toQueueArray();
1706                                 }
1707                         }
1708                         else
1709                         {
1710                                 foreach ($responseData as $rowId => $record)
1711                                 {
1712                                         $responseData[$rowId] = $record->toSynchArray();
1713                                 }
1714                         }
1715                 }
1716                 else
1717                 {
1718                         //-- Synchronization modification from entity context.
1719                         $filter = '1=1';
1720                         $filter .= defined($entityName . '::JOB_QUEUE')
1721                                 ? ' AND a.queueStatus = 1'
1722                                 : '';
1723                         $filter .= $entityName::ARCHIVE
1724                                 ? ' AND a.archived = 0'
1725                                 : '';
1726                         if (method_exists($entityName, 'getSynchFilter'))
1727                         {
1728                                 $synchMod = $entityName::getSynchFilter();
1729                         }
1730                         else
1731                         {
1732                                 $synchMod = array(
1733                                         'Join'   => '',
1734                                         'Filter' => ''
1735                                 );
1736                         }
1737
1738                         //-- Get latest version number.
1739                         $versionResult = $this->em->createQuery(
1740                                 "SELECT MAX(a.createVersion) AS maxCreateVersion, "
1741                                 . " MAX(a.updateVersion) AS maxUpdateVersion "
1742                                 . "FROM $entityName a "
1743                                 . $synchMod['Join']
1744                                 . "WHERE $filter " . $synchMod['Filter']
1745                                 . " ORDER BY a.id ASC"
1746                         )
1747                                 ->getScalarResult();
1748                         $maxVersion    = $versionResult[0]['maxCreateVersion'];
1749                         if ($maxVersion < $versionResult[0]['maxUpdateVersion'])
1750                         {
1751                                 $maxVersion = $versionResult[0]['maxUpdateVersion'];
1752                         }
1753
1754                         //-- Records to add.
1755                         $query                  = "SELECT [SELECTION] "
1756                                                   . "FROM $entityName a "
1757                                                   . $synchMod['Join']
1758                                                   . "WHERE a.archived = :archived"
1759                                                   . " AND $filter " . $synchMod['Filter']
1760                                                   . " AND a.createVersion BETWEEN :version AND :maxVersion"
1761                                                   . " ORDER BY a.id ASC";
1762                         $params                 = array(
1763                                 'archived'   => false,
1764                                 'version'    => $version,
1765                                 'maxVersion' => $maxVersion
1766                         );
1767                         $queryResult            = $this->em->createQuery(
1768                                 str_replace('[SELECTION]', 'a', $query)
1769                         )
1770                                 ->setParameters($params)
1771                                 ->iterate();
1772                         $responseData['Create'] = array();
1773                         if (defined($entityName . '::JOB_QUEUE'))
1774                         {
1775                                 foreach ($queryResult as $rowId => $record)
1776                                 {
1777                                         $responseData['Create'][$rowId] = $record[0]->toQueueArray();
1778                                 }
1779                         }
1780                         else
1781                         {
1782                                 foreach ($queryResult as $rowId => $record)
1783                                 {
1784                                         $responseData['Create'][$rowId] = $record[0]->toSynchArray();
1785                                 }
1786                         }
1787
1788                         //-- Records to update.
1789                         $query                  = "SELECT [SELECTION] "
1790                                                   . "FROM $entityName a "
1791                                                   . $synchMod['Join']
1792                                                   . "WHERE a.archived = :archived"
1793                                                   . " AND $filter " . $synchMod['Filter']
1794                                                   . " AND a.createVersion < :version"
1795                                                   . " AND a.updateVersion BETWEEN :version AND :maxVersion"
1796                                                   . " ORDER BY a.id ASC";
1797                         $params                 = array(
1798                                 'archived'   => false,
1799                                 'version'    => $version,
1800                                 'maxVersion' => $maxVersion
1801                         );
1802                         $queryResult            = $this->em->createQuery(
1803                                 str_replace('[SELECTION]', 'a', $query)
1804                         )
1805                                 ->setParameters($params)
1806                                 ->iterate();
1807                         $responseData['Update'] = array();
1808                         if (defined($entityName . '::JOB_QUEUE'))
1809                         {
1810                                 foreach ($queryResult as $rowId => $record)
1811                                 {
1812                                         $responseData['Update'][$rowId] = $record[0]->toQueueArray();
1813                                 }
1814                         }
1815                         else
1816                         {
1817                                 foreach ($queryResult as $rowId => $record)
1818                                 {
1819                                         $responseData['Update'][$rowId] = $record[0]->toSynchArray();
1820                                 }
1821                         }
1822
1823                         //-- Records to remove.
1824                         $responseData['Delete'] = array();
1825                 }
1826
1827                 //-- Done.
1828                 return new \Zend\View\Model\JsonModel(
1829                         array(
1830                                 'Status' => 'Success',
1831                                 'Reason' => 'Awesomeness.',
1832                                 'Data'   => array(
1833                                         'version'  => $maxVersion,
1834                                         'strategy' => $entityName::PULL_SYNCH_STRATEGY,
1835                                         'changes'  => $responseData
1836                                 )
1837                         )
1838                 );
1839         }
1840
1841
1842
1843         /**
1844          * Utility to send stuff to Trade Center.
1845          * @param $valuationItem
1846          * @param $stock
1847          * @return bool
1848          */
1849         private function sendStockToTradeCenter($valuationItem, $stock)
1850         {
1851                 //-- Pass it along.
1852                 try
1853                 {
1854                         $input  = new \Workspace\Utility\ServiceInput('ParamSet', array(
1855                                 'id'      => $stock->id,
1856                                 'Context' => array()
1857                         ));
1858                         $wStock = $this->serviceLocator->get('Stock');
1859                         $wStock->loadJob($stock->id);
1860                         $wStock->directRoute('Stock.SendToTradeCenter', $stock->id);
1861                 }
1862                 catch (\Exception $e)
1863                 {
1864                         \Utility\Debug::errorLog(__METHOD__ . ':EXCEPTION', $e->getMessage());
1865                         \Utility\Debug::errorLog(__METHOD__ . ':TRACE', $e->getTraceAsString());
1866                         return false;
1867                 }
1868                 return true;
1869         }
1870
1871
1872
1873         /**
1874          * Utility to send stuff to Auction.
1875          * @param $valuationItem
1876          * @param $stock
1877          * @return bool
1878          */
1879         private function sendToAuction($valuationItem, $stock)
1880         {
1881         //\Utility\Debug::errorLog('sendToAuction $valuationItem', $valuationItem);
1882
1883                 //-- Update trade and retail pricing.
1884                 if (8 != $stock->type->category->id)
1885                 {
1886                         try
1887                         {
1888                                 $tu   = new \Utility\Comms\TransUnion();
1889                                 $data = $tu->searchByMmCode(
1890                                         $stock->type->mmCode,
1891                                         $stock->vehicleYear->name,
1892                                         null,
1893                                         null
1894                                 );
1895                         }
1896                         catch (\Exception $e)
1897                         {
1898                                 $data = false;
1899                                 \Utility\Debug::errorLog(
1900                                         'Exception on fetching trade and retail for Device send to auction',
1901                                         $e->getMessage()
1902                                 );
1903                         }
1904                         if (is_array($data)
1905                             && isset($data['VehicleDetails'])
1906                             && isset($data['VehicleDetails'][0])
1907                             && isset($data['VehicleDetails'][0]['Value'])
1908                         )
1909                         {
1910                                 $this->tradePriceDate    = new \DateTime('now');
1911                                 $this->oldTradePriceDate = new \DateTime('now');
1912                                 $this->listPriceDate     = new \DateTime('now');
1913                                 $this->oldListPriceDate  = new \DateTime('now');
1914                                 $stock->oldTradePrice    = $stock->tradePrice;
1915                                 $stock->oldRetailPrice   = $stock->retailPrice;
1916                                 $stock->oldListPrice     = $stock->listPrice;
1917                                 $stock->tradePrice       = $data['VehicleDetails'][0]['Value']['TradePrice'];
1918                                 $stock->retailPrice      = $data['VehicleDetails'][0]['Value']['RetailPrice'];
1919                                 $stock->listPrice        = $data['VehicleDetails'][0]['Value']['NewPrice'];
1920                                 $this->em->flush($stock);
1921                         }
1922                 }
1923
1924                 //-- Pass it along.
1925                 try
1926                 {
1927                         $input        = new \Workspace\Utility\ServiceInput('ParamSet', array(
1928                                 'id'      => $stock->id,
1929                                 'Context' => array(
1930                                         'endDate'      => date('Y-m-d H:i:s', ((int)$valuationItem['auctionEndDate'] / 1000)),
1931                                         'reservePrice' => $valuationItem['auctionReservePrice'],
1932                                         'profileId'    => $this->profileId
1933                                 )
1934                         ));
1935                         $serviceInput = new \Workspace\Utility\ServiceInput('ServiceInput', array(
1936                                 'data' => $input->pack()
1937                         ));
1938                         $wStock       = $this->serviceLocator->get('Stock');
1939                         $wStock->loadJob($stock->id);
1940                         $wStock->executeRoute('Stock.SendToAuction', $stock->id, $serviceInput->pack());
1941                 }
1942                 catch (\Exception $e)
1943                 {
1944                         \Utility\Debug::errorLog(__METHOD__ . ':EXCEPTION', $e->getMessage());
1945                         \Utility\Debug::errorLog(__METHOD__ . ':TRACE', $e->getTraceAsString());
1946                         return false;
1947                 }
1948                 return true;
1949         }
1950
1951
1952
1953         /**
1954          * Utility to send stuff to Valuator(s).
1955          * @param $valuationItem
1956          * @param $valuation
1957          * @return bool
1958          */
1959         private function sendToValuator($valuationItem, $valuation)
1960         {
1961                 //-- Pass it along.
1962                 try
1963                 {
1964                         $input        = new \Workspace\Utility\ServiceInput('ParamSet', array(
1965                                 'id'        => $valuation->id,
1966                                 'Valuation' => array(
1967                                         'valuators' => isset($valuationItem['valuators'])
1968                                                 ? $valuationItem['valuators']
1969                                                 : array($valuationItem['valuator'])
1970                                 )));
1971                         $serviceInput = new \Workspace\Utility\ServiceInput('ServiceInput', array(
1972                                 'data' => $input->pack()
1973                         ));
1974                         $sValuation   = new \Valuation\Service\Valuation();
1975                         $sValuation->setWorkflow($this->serviceLocator->get('Valuation'));
1976                         $sValuation->sendToValuators(array(), $valuation, $valuation, $serviceInput->pack());
1977                 }
1978                 catch (\Exception $e)
1979                 {
1980                         \Utility\Debug::errorLog(__METHOD__ . ':EXCEPTION', $e->getMessage());
1981                         \Utility\Debug::errorLog(__METHOD__ . ':TRACE', $e->getTraceAsString());
1982                         return false;
1983                 }
1984                 return true;
1985         }
1986
1987
1988
1989         /**
1990          * Utility to send stuff to Price Guide.
1991          * @param $valuationItem
1992          * @param $valuation
1993          * @return bool
1994          */
1995         private function sendValuationToPriceGuide($valuationItem, $valuation)
1996         {
1997                 //-- Which clubs to send to?
1998                 $clubs = $this->em->getRepository('PriceGuide\\Entity\\Club')
1999                         ->findBy(
2000                                 array(
2001                                         'company'      => $valuationItem['dealerId'],
2002                                         'useAsDefault' => true,
2003                                         'archived'     => false
2004                                 )
2005                         );
2006                 if (0 == count($clubs))
2007                 {
2008                         $clubs = $this->em->getRepository('PriceGuide\\Entity\\Club')
2009                                 ->findBy(
2010                                         array(
2011                                                 'company'  => $valuationItem['dealerId'],
2012                                                 'archived' => false
2013                                         )
2014                                 );
2015                 }
2016                 if (0 == count($clubs))
2017                 {
2018                         //-- No clubs to send to, abort.
2019                         return false;
2020                 }
2021
2022                 //-- Pass it along the complicated internal process.
2023                 $sendTo = array();
2024                 foreach ($clubs as $club)
2025                 {
2026                         $sendTo[] = array('id' => $club->id);
2027                 }
2028                 try
2029                 {
2030                         $input        = new \Workspace\Utility\ServiceInput('ParamSet', array(
2031                                 'id'        => $valuation->id,
2032                                 'Context'   => array(
2033                                         'clubs' => $sendTo
2034                                 ),
2035                                 'Valuation' => array(
2036                                         'firstName'  => $valuation->firstName,
2037                                         'familyName' => $valuation->familyName,
2038                                         'mobile'     => $valuation->mobile
2039                                 ),
2040                                 'Stock'     => array(
2041                                         'vehicleYear'        => $valuation->stock->vehicleYear->id,
2042                                         'type'               => $valuation->stock->type->id,
2043                                         'registrationNumber' => $valuation->stock->registrationNumber,
2044                                         'fuelType'           => $valuation->stock->fuelType->id,
2045                                         'transmissionType'   => $valuation->stock->transmissionType->id
2046                                 )));
2047                         $serviceInput = new \Workspace\Utility\ServiceInput('ServiceInput', array(
2048                                 'data' => $input->pack()
2049                         ));
2050                         $wValuation   = $this->serviceLocator->get('Valuation');
2051                         $wValuation->loadJob($valuation->id);
2052                         $wValuation->executeRoute('Valuation.SendToPriceGuide', $valuation->id, $serviceInput->pack());
2053                 }
2054                 catch (\Exception $e)
2055                 {
2056                         \Utility\Debug::errorLog(__METHOD__ . ':EXCEPTION', $e->getMessage());
2057                         \Utility\Debug::errorLog(__METHOD__ . ':TRACE', $e->getTraceAsString());
2058                         return false;
2059                 }
2060                 return true;
2061         }
2062
2063         /**
2064          * Utility to send stuff to Price Guide.
2065          * @param $valuationItem
2066          * @param $stock
2067          * @return bool
2068          */
2069         private function sendStockToPriceGuide($valuationItem, $stock)
2070         {
2071                 //-- Which clubs to send to?
2072                 $clubs = $this->em->getRepository('PriceGuide\\Entity\\Club')
2073                         ->findBy(
2074                                 array(
2075                                         'company'      => $valuationItem['dealerId'],
2076                                         'useAsDefault' => true,
2077                                         'archived'     => false
2078                                 )
2079                         );
2080                 if (0 == count($clubs))
2081                 {
2082                         $clubs = $this->em->getRepository('PriceGuide\\Entity\\Club')
2083                                 ->findBy(
2084                                         array(
2085                                                 'company'  => $valuationItem['dealerId'],
2086                                                 'archived' => false
2087                                         )
2088                                 );
2089                 }
2090                 if (0 == count($clubs))
2091                 {
2092                         //-- No clubs to send to, abort.
2093                         return false;
2094                 }
2095
2096                 //-- Pass it along the complicated internal process.
2097                 $sendTo = array();
2098                 foreach ($clubs as $club)
2099                 {
2100                         $sendTo[] = array('id' => $club->id);
2101                 }
2102                 try
2103                 {
2104                         $input        = new \Workspace\Utility\ServiceInput('ParamSet', array(
2105                                 'id'      => $stock->id,
2106                                 'Context' => array(
2107                                         'clubs' => $sendTo
2108                                 )));
2109                         $serviceInput = new \Workspace\Utility\ServiceInput('ServiceInput', array(
2110                                 'data' => $input->pack()
2111                         ));
2112                         $wStock       = $this->serviceLocator->get('Stock');
2113                         $wStock->loadJob($stock->id);
2114                         $wStock->executeRoute('Stock.SendToPriceGuide', $stock->id, $serviceInput->pack());
2115                 }
2116                 catch (\Exception $e)
2117                 {
2118                         \Utility\Debug::errorLog(__METHOD__ . ':EXCEPTION', $e->getMessage());
2119                         \Utility\Debug::errorLog(__METHOD__ . ':TRACE', $e->getTraceAsString());
2120                         return false;
2121                 }
2122                 return true;
2123         }
2124
2125
2126
2127         /**
2128          * Build valuation data for device..
2129          * @param \Stock\Entity\Stock $stock
2130          * @return array
2131          */
2132         private function buildValuationData($stock)
2133         {
2134                 //-- Valuation data.
2135                 $responseData = array(
2136                         'uvi'                            => (int)$stock->uvi,
2137                         'profileId'                      => $stock->createdBy->id,
2138                         'dealerId'                       => $stock->company->id,
2139                         'tradeCenterId'                  => 'Trade Center' == $stock->jobState && !is_null($stock->company->tradeCenter)
2140                                 ? $stock->company->tradeCenter->id
2141                                 : 0,
2142
2143                         'customerName'                   => !is_null($stock->valuation)
2144                                 ? $stock->valuation->firstName
2145                                 : '',
2146                         'customerSurname'                => !is_null($stock->valuation)
2147                                 ? $stock->valuation->familyName
2148                                 : '',
2149                         'customerCellNumber'             => !is_null($stock->valuation)
2150                                 ? $stock->valuation->mobile
2151                                 : '',
2152
2153                         'vehicleYearId'                  => $stock->vehicleYear->id,
2154                         'vehicleCategoryId'              => $stock->type->category->id,
2155                         'vehicleMakeId'                  => $stock->type->model->make->id,
2156                         'vehicleModelId'                 => $stock->type->model->id,
2157                         'vehicleModelTypeId'             => $stock->type->id,
2158                         'vehicleConditionId'             => !is_null($stock->condition)
2159                                 ? $stock->condition->id
2160                                 : 0,
2161                         'vehicleMileage'                 => $stock->km,
2162
2163                         'vehicleMakeName'                => $stock->type->model->make->name,
2164                         'vehicleModelName'               => $stock->type->model->name,
2165
2166                         'tradePrice'                     => (float)$stock->tradePrice,
2167                         'retailPrice'                    => (float)$stock->retailPrice,
2168                         'listPrice'                      => (float)$stock->listPrice,
2169
2170                         'licenceNumber'                  => $stock->registrationNumber,
2171                         'vinNumber'                      => $stock->vinNumber,
2172                         'engineNumber'                   => $stock->engineNumber,
2173                         'fuelTypeId'                     => !is_null($stock->fuelType)
2174                                 ? $stock->fuelType->id
2175                                 : 0,
2176                         'transmissionTypeId'             => !is_null($stock->transmissionType)
2177                                 ? $stock->transmissionType->id
2178                                 : 0,
2179                         'exteriorColourId'               => !is_null($stock->exteriorColour)
2180                                 ? $stock->exteriorColour->id
2181                                 : 0,
2182                         'interiorColourId'               => !is_null($stock->interiorColour)
2183                                 ? $stock->interiorColour->id
2184                                 : 0,
2185                         'upholsteryId'                   => !is_null($stock->upholstery)
2186                                 ? $stock->upholstery->id
2187                                 : 0,
2188                         'spareKeysId'                    => is_null($stock->spareKeys)
2189                                 ? -1
2190                                 : ($stock->spareKeys ? 0 : 1),
2191                         'fullServiceHistoryId'           => !is_null($stock->fullServiceHistory)
2192                                 ? $stock->fullServiceHistory->id
2193                                 : 0,
2194                         'fullServiceHistoryNotes'        => $stock->fshNotes,
2195
2196                         'accessories'                    => '',
2197                         'accessoriesComments'            => $stock->accessoryNotes,
2198                         'damages'                        => array(),
2199                         'damagesEstimatedRepairCost'     => (float)$stock->damageTotal,
2200                         'damagesComments'                => $stock->damageNotes,
2201                         'damagesPreviousRepairsNoted'    => $stock->previousRepairsNoted,
2202                         'damagesPreviousRepairsComments' => $stock->previousRepairsNotes,
2203
2204                         'owner'                          => !is_null($stock->valuation)
2205                                                             && 'Valuation' == $stock->jobState
2206                                 ? 'Valuation'
2207                                 : 'Stock',
2208                         'status'                         => !is_null($stock->valuation)
2209                                                             && 'Valuation' == $stock->jobState
2210                                 ? $stock->valuation->jobState
2211                                 : $stock->jobState,
2212                         'queueStatus'                    => !is_null($stock->valuation)
2213                                 ? $stock->valuation->queueStatus
2214                                 : 0,
2215                         'offer'                          => !is_null($stock->valuation)
2216                                 ? (float)$stock->valuation->amountOffered
2217                                 : 0.0,
2218                         'stockNumber'                    => $stock->stockNumber,
2219                         'auctionEndDate'                 => !is_null($stock->auction)
2220                                                             && 'Active' == $stock->auction->jobState
2221                                 ? $stock->auction->endDate->getTimestamp() * 1000
2222                                 : 0,
2223                         'auctionReservePrice'            => !is_null($stock->auction)
2224                                 ? (float)$stock->auction->reservePrice
2225                                 : 0.0,
2226                         'photos'                         => array()
2227                 );
2228                 if ('Stock' == $stock->jobState
2229                     && !is_null($stock->auction)
2230                     && 'Relist' == $stock->auction->jobState
2231                 )
2232                 {
2233                         $responseData['status'] = 'Relist';
2234                 }
2235
2236 //        \Utility\Debug::errorLog('buildValuationData $responseData', $responseData);
2237
2238                 //-- Linked accessories.
2239                 $accessories = array();
2240                 foreach ($stock->accessories as $accessory)
2241                 {
2242                         $accessories[] = $accessory->accessory->id;
2243                 }
2244                 if (0 < count($accessories))
2245                 {
2246                         $responseData['accessories'] = implode(':', $accessories);
2247                 }
2248
2249                 //-- Linked damages.
2250                 $damages = array();
2251                 foreach ($stock->damages as $damage)
2252                 {
2253                         if ($damage->archived)
2254                         {
2255                                 continue;
2256                         }
2257                         $damages[] = array(
2258                                 'serverId' => $damage->damage->id,
2259                                 'amount'   => (float)$damage->amount
2260                         );
2261                 }
2262                 $responseData['damages'] = $damages;
2263
2264                 //-- Photos
2265                 $photoMap = array(
2266                         'main',
2267                         'front',
2268                         'right',
2269                         'left',
2270                         'back',
2271                         'interior',
2272                         'engine',
2273                         'natis'
2274                 );
2275                 $photos   = array();
2276                 foreach ($photoMap as $type)
2277                 {
2278                         $fieldName = $type . 'Image';
2279                         if (!is_null($stock->$fieldName))
2280                         {
2281                                 $photos[] = array(
2282                                         'uvi'      => (int)$stock->uvi,
2283                                         'serverId' => $stock->$fieldName->id,
2284                                         'type'     => $type,
2285                                         'webUri'   => '/img/bin/thumbnail/' . $stock->$fieldName->filename
2286                                 );
2287                         }
2288                 }
2289                 $responseData['photos'] = $photos;
2290                 return $responseData;
2291         }
2292
2293         /**
2294          * Image resizing.
2295          * @param $imgString
2296          * @param $mimeType
2297          * @param $destination
2298          * @return bool
2299          */
2300         private function resizeImage($imgString, $mimeType, $destination)
2301         {
2302                 $tmpFile = $destination;
2303                 file_put_contents($tmpFile, $imgString);
2304                 list($img_width, $img_height) = getimagesize($tmpFile);
2305                 unlink($tmpFile);
2306                 if (!$img_width || !$img_height)
2307                 {
2308                         return false;
2309                 }
2310                 $src_img = imagecreatefromstring($imgString);
2311                 $scale   = min(
2312                         300 / $img_width,
2313                         200 / $img_height
2314                 );
2315                 if ($scale >= 1)
2316                 {
2317                         file_put_contents($tmpFile, $imgString);
2318                         return true;
2319                 }
2320                 $new_width  = $img_width * $scale;
2321                 $new_height = $img_height * $scale;
2322                 $new_img    = @imagecreatetruecolor($new_width, $new_height);
2323                 switch ($mimeType)
2324                 {
2325                         case 'image/jpeg':
2326                         case 'image/pjpeg':
2327                                 $write_image   = 'imagejpeg';
2328                                 $image_quality = 95;
2329                                 break;
2330                         case 'image/gif':
2331                                 @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0));
2332                                 $write_image   = 'imagegif';
2333                                 $image_quality = null;
2334                                 break;
2335                         case 'image/png':
2336                                 @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0));
2337                                 @imagealphablending($new_img, false);
2338                                 @imagesavealpha($new_img, true);
2339                                 $write_image   = 'imagepng';
2340                                 $image_quality = 9;
2341                                 break;
2342                         case 'image/bmp':
2343                         case 'image/x-windows-bmp':
2344                                 $write_image   = 'imagebmp';
2345                                 $image_quality = null;
2346                                 break;
2347                         default:
2348                                 return false;
2349                 }
2350                 $success = @imagecopyresampled(
2351                         $new_img,
2352                         $src_img,
2353                         0, 0, 0, 0,
2354                         $new_width,
2355                         $new_height,
2356                         $img_width,
2357                         $img_height
2358                 );
2359                 if ($success)
2360                 {
2361                         $write_image($new_img, $tmpFile, $image_quality);
2362                         @imagedestroy($src_img);
2363                         @imagedestroy($new_img);
2364                         return true;
2365                 }
2366                 @imagedestroy($src_img);
2367                 @imagedestroy($new_img);
2368                 return false;
2369         }
2370
2371         /**
2372          * @return array
2373          * @throws \Doctrine\ORM\ORMException
2374          * @throws \Doctrine\ORM\OptimisticLockException
2375          * @throws \Doctrine\ORM\TransactionRequiredException
2376          */
2377         protected function getAuctionAllowedDays()
2378         {
2379                 //-- Establish dealer group for user.
2380                 $openDays = array();
2381                 $profile  = $this->em->find('User\\Entity\\Profile', $this->profileId);
2382                 $groupId  = null;
2383                 if (!is_null($profile->company)
2384                     && !is_null($profile->company->groupDivision)
2385                     && !is_null($profile->company->groupDivision->group)
2386                 )
2387                 {
2388                         $groupId = $profile->company->groupDivision->group->id;
2389                 }
2390                 if (!is_null($groupId))
2391                 {
2392                         //-- Get open days for relevant group.
2393                         $days = $this->em->createQuery(
2394                                 'SELECT openDayGroup, openDay '
2395                                 . 'FROM Auction\\Entity\\OpenDayGroup openDayGroup '
2396                                 . 'JOIN openDayGroup.openDay openDay '
2397                                 . 'WHERE IDENTITY(openDayGroup.companyGroup) = :groupId'
2398                                 . ' AND openDay.openDate > :startDate'
2399                         )
2400                                 ->setParameter('groupId', $groupId)
2401                                 ->setParameter('startDate', new \DateTime('now'))
2402                                 ->getResult();
2403                         foreach ($days as $publicDay)
2404                         {
2405                                 $openDays[] = $publicDay->openDay->openDate->format('Y-m-d');
2406                         }
2407                 }
2408
2409                 //-- Get public holidays.
2410                 $publicDays = array();
2411                 $days       = $this->em->createQuery(
2412                         'SELECT publicHoliday '
2413                         . 'FROM Auction\\Entity\\PublicHoliday publicHoliday '
2414                         . 'WHERE publicHoliday.holiday > :startDate'
2415                 )
2416                         ->setParameter('startDate', new \DateTime('now'))
2417                         ->getResult();
2418                 foreach ($days as $publicDay)
2419                 {
2420                         $publicDays[] = $publicDay->holiday->format('Y-m-d');
2421                 }
2422                 $days = null;
2423
2424                 //-- Get auction max days.
2425                 $config  = \Utility\Cache::fetchEntity(
2426                         'Config\Entity\Config', 1, \Utility\Registry::getEntityManager(), 600
2427                 );
2428                 $maxDays = $config['auctionMaxDays'];
2429
2430                 //-- Compute.
2431                 $day     = time() + 86400;
2432                 $allowed = array();
2433                 if ($this->canUseAuctionDay($day, $openDays, $publicDays))
2434                 {
2435                         $allowed[] = date('Y-m-d', $day);
2436                 }
2437                 for ($i = 1; $i < $maxDays; $i++)
2438                 {
2439                         //-- Move to next day.
2440                         $day += 86400;
2441
2442                         //-- Check if we can use this day.
2443                         if ($this->canUseAuctionDay($day, $openDays, $publicDays))
2444                         {
2445                                 $allowed[] = date('Y-m-d', $day);
2446                         }
2447                 }
2448                 return $allowed;
2449         }
2450
2451 }