text changes to registration mail content
[namibia] / module / Auction / src / Auction / Service / AutoBid.php
1 <?php
2 namespace Auction\Service;
3
4
5
6 /**
7  * Manage Offer data.
8  * @author andre.fourie
9  */
10 class AutoBid extends \Auction\DataBin\AutoBid
11 {
12
13         protected $_increments = null;
14
15         /**
16          * Retrieve next higher auto-increment rule.
17          * @param unknown $price
18          * @return \Auction\Entity\Increment
19          */
20         public function _getNextIncrement($price)
21         {
22                 if (!$this->_increments)
23                 {
24                         $this->_increments = $this->em
25                                 ->getRepository('\Auction\Entity\Increment')
26                                 ->findBy(array(), array('to' => 'ASC'));
27                 }
28                 foreach ($this->_increments as $incr)
29                 {
30                         if ($incr->from >= $price)
31                         {
32                                 return $incr;
33                         }
34                 }
35                 return false;
36         }
37
38         /**
39          * ExecuteAfter: Create.
40          * Handle bidding details.
41          * @param array $meta
42          * @param object|null $jobRecord
43          * @param object|null $record
44          * @param \Workspace\Utility\ServiceInputParams $contract
45          * @return array
46          */
47         public function updateStatus($meta, $auction, $record, \Workspace\Utility\ServiceInputParams $contract)
48         {
49                 #-> Collect some info.
50                 $basket = $this->em
51                         ->getRepository('\Auction\Entity\Basket')
52                         ->findOneBy(array(
53                                 'auction' => $auction->id,
54                                 'company' => $record->company->id
55                         ));
56                 if (is_null($basket))
57                 {
58                         $basket = new \Auction\Entity\Basket();
59                         $basket->fromArray(array(
60                                         'auction' => $auction,
61                                         'company' => $record->company,
62                                         'profile' => $record->profile
63                         ));
64                         $this->em->persist($basket);
65                         $this->em->flush($basket);
66                 }
67                 elseif (true == $basket->archived)
68                 {
69                         $basket->archived = false;
70                         $this->em->flush($basket);
71                 }
72                 if ($auction->reservePrice > $record->amount)
73                 {
74                         $record->status = 'Archived';
75                         $this->em->flush($record);
76                         throw new \Exception('Your bid was placed but you were just outbid.');
77                         return;
78                 }
79                 $newCurrentBid = false;
80                 $newBid        = null;
81                 $oldBid        = null;
82                 $doNotify      = false;
83
84                 #-> Lockdown some working space.
85                 $this->em->clear();
86                 $this->em->getConnection()->beginTransaction();
87                 $rsm = new \Doctrine\ORM\Query\ResultSetMappingBuilder($this->em);
88                 $rsm->addRootEntityFromClassMetadata('\Auction\Entity\Auction', 'auction');
89                 $query = $this->em->createNativeQuery("SELECT * FROM auction WHERE id = :id FOR UPDATE", $rsm);
90                 $query->setParameter("id", $auction->id);
91                 $jobRecord = $query->getOneOrNullResult();
92                 $cBidId = $jobRecord->currentBid
93                         ? $jobRecord->currentBid->id
94                         : 0;
95                 $aBidId = $jobRecord->currentBid && $jobRecord->currentBid->autoBid
96                         ? $jobRecord->currentBid->autoBid->id
97                         : 0;
98                 $record = $this->em->find('\Auction\Entity\AutoBid', $record->id);
99
100                 #-> Safety check.
101                 if ('Active' != $jobRecord->jobState
102                         || time() > $jobRecord->endDate->getTimestamp())
103                 {
104                         $record->status = 'Archived';
105                         $this->em->flush($record);
106                         $this->em->getConnection()->commit();
107                         throw new \Exception('Your bid could not be placed. This auction item have been closed.');
108                         return;
109                 }
110
111                 #-> Some more info.
112                 $base = $jobRecord->currentBidPrice != 0.0
113                                         ? $jobRecord->currentBidPrice
114                                         : $jobRecord->reservePrice;
115                 $nextRule = $this->_getNextIncrement($base);
116                 $incr = $jobRecord->bidIncrement;
117
118                 #-> Process.
119 //        $jobRecord->numberOfBids++;
120                 //$record->amount = floor($record->amount / $incr) * $incr;
121                 //$record->amount = ($record->amount / $incr) * $incr;
122                 if ($nextRule && $base >= $nextRule->from)
123                 {
124                         $jobRecord->bidIncrement = $nextRule->amount;
125                         $incr = $nextRule->amount;
126                         $nextRule = $this->_getNextIncrement($base);
127                 }
128                 $base += $incr;
129                 if (is_null($jobRecord->currentBid))
130                 {
131                         #-> First bid on this item.
132                         $atBid = new \Auction\Entity\Bid();
133                         $atBid->fromArray(array(
134                                 'auction' => $jobRecord,
135                                 'company' => \Utility\Registry::resolveCompanyContext(null),
136                                 'profile' => \Utility\Registry::resolveProfileContext(null),
137                                 'autoBid' => $record,
138                                 'amount'  => $jobRecord->reservePrice + $incr
139                         ));
140                         $this->em->persist($atBid);
141                         $this->em->flush($atBid);
142                         $newCurrentBid = true;
143                         $newBid = $atBid;
144             $jobRecord->numberOfBids++;
145                 }
146                 elseif ($jobRecord->currentBidPrice + $incr >= $record->amount
147                         || $jobRecord->currentBid->company->id == $record->company->id)
148                 {
149                         #-> Late arrival or useless hack.
150                         $record->status = 'Archived';
151                         $this->em->flush($record);
152                         if ($jobRecord->currentBid->company->id == $record->company->id)
153                         {
154                                 throw new \Exception('Your bid was not successfull. Your dealership already has the winning bid.');
155                         }
156                         else
157                         {
158                                 throw new \Exception('Your bid was too low, please place a bid higher than R' . ($jobRecord->currentBidPrice + $incr));
159                         }
160                         $doNotify = true;
161                         $oldBid = $record;
162 //            $jobRecord->numberOfBids++;
163                 }
164                 else
165                 {
166                         #-> Competing bids, figure it out.
167                         $doNotify = true;
168                         if (!is_null($jobRecord->currentBid->autoBid))
169                         {
170                                 #-> Auto-bid against existing auto-bid.
171                                 $price   = $jobRecord->currentBidPrice;
172                                 $prevBid = $jobRecord->currentBid->autoBid->amount;
173                                 $newBid  = $record->amount;
174                                 $win     = false;
175                                 $bidder  = 0; // 0:prev auto, 1:new auto
176                                 //error_log('Prev max: ' . $prevBid);
177                                 //error_log('New max: ' . $newBid);
178                                 while (!$win)
179                                 {
180                                         $price += $incr;
181                                         $bidder = (0 == $bidder)
182                                                 ? 1
183                                                 : 0;
184                                         /* error_log((0 == $bidder)
185                                                 ? 'Previous bidder bids @ ' . $price
186                                                 : 'New bidder bids @ ' . $price); */
187                                         $autoMax = (0 == $bidder)
188                                                 ? $prevBid
189                                                 : $newBid;
190                                         if ($price > $autoMax)
191                                         {
192                                                 #-> Winning bid.
193                                                 //error_log('somebody is over max');
194                                                 $price -= $incr;
195                                                 $win = true;
196                                                 if (1 == $bidder || $price <= $prevBid)
197                                                 {
198                                                         //error_log('Prev wins');
199                                                         /* $atBid = new \Auction\Entity\Bid();
200                                                         $atBid->fromArray(array(
201                                                                 'auction' => $jobRecord,
202                                                                 'company' => $jobRecord->currentBid->company,
203                                                                 'profile' => $jobRecord->currentBid->profile,
204                                                                 'autoBid' => $jobRecord->currentBid->autoBid,
205                                                                 'amount'  => $price
206                                                         ));
207                                                         $this->em->persist($atBid);
208                                                         $this->em->flush($atBid); */
209                                                         $newCurrentBid = true;
210                                                         $newBid = $atBid;
211                                                         $oldBid = $record;
212                                                         $record->status = 'Archived';
213                                                         $this->em->flush($record);
214                                                 }
215                                                 else
216                                                 {
217                                                         //error_log('New wins');
218                                                         /* $atBid = new \Auction\Entity\Bid();
219                                                         $atBid->fromArray(array(
220                                                                         'auction' => $jobRecord,
221                                                                         'company' => $record->company,
222                                                                         'profile' => $record->profile,
223                                                                         'autoBid' => $record,
224                                                                         'amount'  => $price
225                                                         ));
226                                                         $this->em->persist($atBid);
227                                                         $this->em->flush($atBid); */
228                                                         $newCurrentBid = true;
229                                                         $newBid = $atBid;
230                                                         $oldBid = $jobRecord->currentBid;
231                                                         $jobRecord->currentBid->autoBid->status = 'Archived';
232                                                         $jobRecord->currentBid->status = 'Archived';
233 //                            $jobRecord->numberOfBids++;
234                                                         $this->em->flush($jobRecord->currentBid->autoBid);
235                                                         $this->em->flush($jobRecord->currentBid);
236                                                 }
237                                         }
238                                         else
239                                         {
240                                                 #-> Not-final bid.
241                                                 if (1 == $bidder)
242                                                 {
243                                                         $atBid = new \Auction\Entity\Bid();
244                                                         $atBid->fromArray(array(
245                                                                         'auction' => $jobRecord,
246                                                                         'company' => $record->company,
247                                                                         'profile' => $record->profile,
248                                                                         'autoBid' => $record,
249                                                                         'amount'  => $price
250                                                         ));
251                                                         $this->em->persist($atBid);
252                                                         $this->em->flush($atBid);
253
254                                                 }
255                                                 else
256                                                 {
257                                                         $atBid = new \Auction\Entity\Bid();
258                                                         $atBid->fromArray(array(
259                                                                         'auction' => $jobRecord,
260                                                                         'company' => $jobRecord->currentBid->company,
261                                                                         'profile' => $jobRecord->currentBid->profile,
262                                                                         'autoBid' => $jobRecord->currentBid->autoBid,
263                                                                         'amount'  => $price
264                                                         ));
265                                                         $this->em->persist($atBid);
266                                                         $this->em->flush($atBid);
267                                                 }
268
269                         $jobRecord->numberOfBids++;
270
271                                         }
272                                         if ($nextRule && $price >= $nextRule->from)
273                                         {
274                                                 $jobRecord->bidIncrement = $nextRule->amount;
275                                                 $incr = $nextRule->amount;
276                                                 $nextRule = $this->_getNextIncrement($price);
277                                                 //$prevBid = floor($jobRecord->currentBid->autoBid->amount / $incr) * $incr;
278                                                 $prevBid = $jobRecord->currentBid->autoBid->amount;
279                                                 //$newBid = floor($record->amount / $incr) * $incr;
280                                                 $newBid = $record->amount;
281 //                        $jobRecord->numberOfBids++;
282                                         }
283
284                                 }
285                         }
286                         else
287                         {
288                                 #-> Auto-bid against bid.
289                                 $price = $jobRecord->currentBidPrice + $incr;
290                                 if ($record->amount >= $price)
291                                 {
292                                         $atBid = new \Auction\Entity\Bid();
293                                         $atBid->fromArray(array(
294                                                         'auction' => $jobRecord,
295                                                         'company' => $record->company,
296                                                         'profile' => $record->profile,
297                                                         'autoBid' => $record,
298                                                         'amount'  => $price
299                                         ));
300                                         $this->em->persist($atBid);
301                                         $this->em->flush($atBid);
302                                         $newCurrentBid = true;
303                                         $newBid = $atBid;
304                                         $oldBid = $jobRecord->currentBid;
305                                         $jobRecord->currentBid->status = 'Archived';
306                                         $this->em->flush($jobRecord->currentBid);
307                     $jobRecord->numberOfBids++;
308                                 }
309                                 else
310                                 {
311                                         $oldBid = $record;
312                                         $record->status = 'Archived';
313                                         $this->em->flush($record);
314                                 }
315
316 //                $jobRecord->numberOfBids++;
317                         }
318                 }
319
320                 #-> Update auction with latest.
321                 if ($newCurrentBid)
322                 {
323                         $jobRecord->currentBid = $newBid;
324                         $jobRecord->currentBidPrice = $newBid->amount;
325                         if ($nextRule && $newBid->amount >= $nextRule->from)
326                         {
327                                 $jobRecord->bidIncrement = $nextRule->amount;
328                                 $incr = $nextRule->amount;
329                         }
330                 }
331
332                 #-> Expiry buffer.
333                 if (time() > ($jobRecord->endDate->getTimestamp() - 300))
334                 {
335                         #-> Move end date out with 5 minutes.
336                         $jobRecord->endDate = new \DateTime(
337                                                 date('Y-m-d H:i:s', $jobRecord->endDate->getTimestamp() + 300)
338                         );
339                         error_log($jobRecord->endDate->getTimestamp());
340                 }
341                 $this->em->flush($jobRecord);
342
343                 #-> Unlock.
344                 $this->em->getConnection()->commit();
345                 //\Utility\Doctrine::unlockTables();
346
347                 #-> Notify clients with updated auction data.
348                 $vehicle = $jobRecord->stock->type->model->make->name
349                         . ', ' . $jobRecord->stock->type->model->name
350                         . ', ' . $jobRecord->stock->type->name
351                         . ' (' . $jobRecord->stock->vehicleYear->name . ')';
352                 if ($newCurrentBid)
353                 {
354                         #-> Update stock entry.
355                         $jobRecord->stock->highestBid = $jobRecord->currentBidPrice;
356                         $this->em->flush();
357
358                         #-> Chat to ape comet server.
359                         \Utility\Comms\Ape::broadcast('LiveAuction', array(
360                                 'id'                => $jobRecord->id,
361                                 'current_bid'       => $jobRecord->currentBid->toArray(array(), array(), 1),
362                                 'current_bid_id'    => $jobRecord->currentBid->id,
363                                 'current_bid_price' => $jobRecord->currentBidPrice,
364                                 'number_of_bids'    => $jobRecord->numberOfBids,
365                                 'expire_datetime'   => $jobRecord->endDate->format(\Utility\Definitions\Locale::getDateTimeFormat()),
366                                 'winner'            => $newBid->company->id,
367                                 'looser'            => !is_null($oldBid) ? $oldBid->company->id : 0,
368                                 'basket'            => $basket->toArray(array(), array(), 1),
369                                 'vehicle'                       => $vehicle
370                                 ));
371                 }
372
373                 #-> Outbid notification.
374                 if ($newCurrentBid && $doNotify)
375                 {
376                         #-> Send email.
377                         $currPrefix = \Utility\Definitions\Locale::getCurrencyPrefix() . ' ';
378                         $oNotify = new \Utility\Comms\Notification();
379                         $oNotify->sendFromTemplate(
380                                         null, null,
381                                         $oldBid->company->id, $oldBid->profile->id,
382                                         null, $oldBid->profile->mobile,
383                                         null,
384                                         'auction-outbid',
385                                         array(
386                                                 'first_name'                    => $oldBid->profile->firstName,
387                                                 'family_name'                   => $oldBid->profile->familyName,
388                                                 'vehicle'                               => $vehicle,
389                                                 'seller'                                => $jobRecord->company->name,
390                                                 'price'                                 => $currPrefix . ($jobRecord->currentBidPrice + $incr),
391                                                 'bid'                                   => $currPrefix . $oldBid->amount,
392                                                 'auction_expiry_date'   => $jobRecord->endDate->format(
393                                                                                                         \Utility\Definitions\Locale::getDateTimeFormat()
394                                                                                                 )
395                                         ));
396                 }
397
398                 #-> Feedback.
399                 if ($newCurrentBid && $record->company->id != $newBid->company->id)
400                 {
401                         throw new \Exception('Your bid was placed but you were just outbid.');
402                 }
403         }
404
405
406
407 }