· 8 years ago · Jan 16, 2017, 05:08 AM
1<?php
2
3namespace ORORI\ApiBundle\Controller\Transaction;
4
5use Aws\Ses\SesClient;
6use Mmoreram\GearmanBundle\Exceptions\JobDoesNotExistException;
7use Mmoreram\GearmanBundle\Exceptions\WorkerDoesNotExistException;
8use ORORI\CoreBundle\Entity\CustomerPoint;
9use ORORI\CoreBundle\Entity\OauthToken;
10use ORORI\CoreBundle\Entity\Payment;
11use ORORI\CoreBundle\Entity\TransactionDetail;
12use ORORI\VoucherBundle\Manager\VoucherManager;
13use Symfony\Component\HttpFoundation\JsonResponse;
14use Symfony\Component\HttpFoundation\Request;
15use Nelmio\ApiDocBundle\Annotation\ApiDoc;
16use ORORI\CoreBundle\Helper\HttpStatusHelper as HttpStatus;
17use ORORI\CoreBundle\Gearman\JobName;
18use ORORI\CoreBundle\Entity\Customer;
19use ORORI\CoreBundle\Entity\Product;
20use ORORI\CoreBundle\Entity\Transaction;
21use ORORI\CoreBundle\Entity\TransactionHistory;
22use ORORI\ApiBundle\Controller\BaseController;
23use ORORI\VoucherBundle\Entity\Voucher;
24use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
25
26class TransactionHistoryController extends BaseController
27{
28 /**
29 * @ApiDoc(
30 * section="Master",
31 * resource="Transaction",
32 * description="Create a transaction history",
33 * parameters={
34 * {"name"="access_token", "dataType"="string", "required"=true, "description"="Customer access token"},
35 * {"name"="transaction_status", "dataType"="string", "required"=true, "description"="0=cancel, 2=pending, 3=processing, 5=delivered"},
36 * {"name"="comment", "dataType"="string", "required"=false, "description"="comment that will be appended to email"},
37 * {"name"="notify_customer", "dataType"="string", "required"=false, "description"="1 send email to customer, 0 doesn't send, default = 1"},
38 * {"name"="lang", "dataType"="string", "required"=false, "format"="en|id",
39 * "description"="response language, using ISO 639-1, default = id"},
40 * },
41 * statusCodes={
42 * 201="Returned when successful",
43 * 400="Bad request",
44 * 401="Unauthorized",
45 * 404="Not found",
46 * 500="System error",
47 * }
48 * )
49 * @Security("has_role('ROLE_TRANSACTION_HISTORY_CREATE')")
50 */
51 public function createAction(Request $req, $id)
52 {
53 $post = $req->request->all();
54 $this->init($post);
55
56 // Validate parameter sent
57 $valid = $this->validateCreateParameter($req);
58 if ($valid instanceof JsonResponse) {
59 return $valid;
60 }
61
62 // Validate access token
63 $token = $this->validateAccessToken($req);
64 if (!$token instanceof OauthToken) {
65 return $token;
66 }
67
68 $currentRole = '';
69 $transTransHistoryHandlerService = $this->container->get('orori.trans.trans_history.handler.api.service');
70 if ($this->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
71 $currentRole = 'ROLE_ADMIN';
72 } elseif ($this->get('security.authorization_checker')->isGranted('ROLE_SALES_HEAD')) {
73 $currentRole = 'ROLE_SALES_HEAD';
74 } elseif ($this->get('security.authorization_checker')->isGranted('ROLE_SALES')) {
75 $currentRole = 'ROLE_SALES';
76 if (!$transTransHistoryHandlerService->isAllowedChoice('ROLE_SALES', $post['transaction_status'])) {
77 return $this->errorResponse(
78 'Not Authorized',
79 null, HttpStatus::HTTP_UNAUTHORIZED
80 );
81 }
82 } elseif ($this->get('security.authorization_checker')->isGranted('ROLE_FINANCE')) {
83 $currentRole = 'ROLE_FINANCE';
84 if (!$transTransHistoryHandlerService->isAllowedChoice('ROLE_FINANCE', $post['transaction_status'])) {
85 return $this->errorResponse(
86 'Not Authorized',
87 null, HttpStatus::HTTP_UNAUTHORIZED
88 );
89 }
90 } elseif ($this->get('security.authorization_checker')->isGranted('ROLE_DELIVERY')) {
91 $currentRole = 'ROLE_DELIVERY';
92 if (!$transTransHistoryHandlerService->isAllowedChoice('ROLE_DELIVERY', $post['transaction_status'])) {
93 return $this->errorResponse(
94 'Not Authorized',
95 null, HttpStatus::HTTP_UNAUTHORIZED
96 );
97 }
98 }
99
100 /* @var $transHistoryRepo \ORORI\CoreBundle\Repository\TransactionHistoryRepository */
101 $transHistoryRepo = $this->em->getRepository('ORORICoreBundle:TransactionHistory');
102 /* @var $transactionRepo \ORORI\CoreBundle\Repository\TransactionRepository */
103 $transactionRepo = $this->em->getRepository('ORORICoreBundle:Transaction');
104 /* @var $productRepo \ORORI\CoreBundle\Repository\ProductRepository */
105 $productRepo = $this->em->getRepository('ORORICoreBundle:Product');
106
107 $transaction = $transactionRepo->findOneBy(array(
108 'id' => $id,
109 'isActive' => true,
110 ));
111 if (!$transaction instanceof Transaction) {
112 return $this->errorResponse(
113 $this->translator->trans('error.not_found', array('%s%' => 'transaction')),
114 null, HttpStatus::HTTP_NOT_FOUND
115 );
116 }
117
118 // Add transaction history
119 $user = $token->getUser();
120 $new = new TransactionHistory();
121 $new->setTransaction($transaction)
122 ->setUser($user)
123 ->setTransactionStatus($post['transaction_status'])
124 ->setCreatedBy($user->getUsername())
125 ;
126
127 $infoMerchandising = false;
128 $infoProducts = [];
129
130 // Cut stock on status processing
131 // Pending -> Processing
132 if ($post['transaction_status'] == Transaction::STATUS_SUPPLIER
133 && $transaction->getStatus() == Transaction::STATUS_PENDING) {
134 $details = $transaction->getTransactionDetail();
135 $customer = $transaction->getCustomer();
136 $totalTransaction = 0;
137 $isMarketplace = false;
138
139 $voucherManager = new VoucherManager();
140 if ($details) {
141 /** @var TransactionDetail $detail */
142 foreach ($details as $detail) {
143 /** @var Product $prod */
144 $prod = $detail->getProduct();
145 $supplier = $prod->getSupplier();
146 $qty = $detail->getCount();
147 $totalTransaction += $detail->getTotalPrice();
148
149 $productData = $productRepo->getFrontendEntityData($prod);
150 $voucherManager->addProduct($prod, $productData, $qty);
151
152 // If marketplace then send email to corresponding supplier
153 if ($supplier instanceof \ORORI\CoreBundle\Entity\Supplier && (int) $supplier->getId() !== 48) {
154 $isMarketplace = true;
155 }
156
157 // Voucher promo
158 if (in_array($prod->getCode(), $productRepo->getVoucherFlashSale())) {
159 $vocCodes = [
160 'VC-FLASH-300-GOLD' => '300k',
161 'VC-FLASH-325-GOLD' => '650k',
162 'VC-FLASH-500-GOLD' => '500k',
163 'VC-FLASH-600-GOLD' => '600k',
164 'VC-FLASH-650-GOLD' => '650k',
165 'VC-FLASH-650-IP' => '650k',
166 'VC-FLASH-1000' => '1000k',
167 'VC-FLASH-1000-GOLD'=> '1000k',
168 ];
169 $voucherRepo = $this->em->getRepository('ORORIVoucherBundle:Voucher');
170 $type = $vocCodes[strtoupper($prod->getCode())];
171 $prefix = 'FSG';
172 $description = 'Flash Sale Transaction '.$transaction->getId();
173 $customer = $transaction->getCustomer();
174 $resultVoucher = array();
175 $voucherValue = 0;
176 $voucherMinimumPrice = 0;
177
178 for ($i = 1; $i <= $qty; $i++) {
179 $voucher = $voucherRepo->generateFreeVoucher($type, $prefix, $description, $customer);
180 $resultVoucher[] = $voucher->getCode();
181 if (!$voucherValue) {
182 $voucherValue = $voucher->getValue();
183 $voucherMinimumPrice = $voucher->getMinimumPrice();
184 }
185 }
186
187 try {
188 $this->get('gearman')->doBackgroundJob(
189 JobName::FLASHSALE_VOUCHER_NOTIF, json_encode([
190 'name' => $customer->getFirstname(),
191 'email' => $customer->getEmail(),
192 'product' => $customer->getEmail(),
193 'voucher_prod' => $prod->getCode(),
194 'voucher_code' => $resultVoucher,
195 'voucher_value' => $voucherValue,
196 'voucher_minPrice' => $voucherMinimumPrice,
197 ]));
198 } catch (JobDoesNotExistException $e) {
199 $this->log($e);
200 } catch (WorkerDoesNotExistException $e) {
201 $this->log($e);
202 }
203 }
204
205 $this->em->persist($prod);
206 // Save to table_modify before flush to make this work
207 $this->logModified($prod, 'TRANSACTION PROCESSING '.$transaction->getId());
208 $this->em->flush();
209 }
210 }
211
212 if ($isMarketplace) {
213 $this->sendEmailToSupplier($transaction, $supplier);
214 }
215
216 /**
217 * Referral Customer
218 */
219 $logger = $this->get('monolog.logger.payment_channel');
220 $customerReferral = $this->get('doctrine.orm.entity_manager')->getRepository('ORORICoreBundle:Customer')->findOneBy(array('uniqueCode' => $transaction->getVoucherCode()));
221 if ($customerReferral) {
222 $logger->info('[REFERRAL] Customer Unique Code'.$customerReferral->getUniqueCode());
223 $logger->info('[REFERRAL] Voucher Code'.$transaction->getVoucherCode());
224 if (strtoupper($transaction->getVoucherCode()) === strtoupper($customerReferral->getUniqueCode()) && $voucherManager->isReferralVoucher($transaction->getVoucherCode())) {
225 $logger->info('[REFERRAL APPLIED]');
226 $point = $voucherManager->getTotalPoint();
227 $logger->info('[REFERRAL POINT] '.$point);
228 if ($customerReferral) {
229 $customerPoint = new CustomerPoint();
230 $customerPoint->setCustomer($customerReferral)
231 ->setPoint('-'.$point)
232 ->setContainer('transaction')
233 ->setContainerId($transaction->getId())
234 ->setDescription('Referral Customer - '.$customerReferral->getId())
235 ->setValidUntil(\DateTime::createFromFormat('Y-m-d', date('Y-m-d')))
236 ->setCreatedAt($this->timeInit)
237 ->setCreatedBy('SYSTEM')
238 ;
239 $customerReferral->setPoint($customerReferral->getPoint() + $point);
240 $this->em->persist($customerPoint);
241 $this->em->persist($customerReferral);
242 }
243 }
244 }
245
246 // Apply gold point
247 if (date('Y-m-d G:i:s') >= Transaction::GOLD_POINT_PERIOD_START && date('Y-m-d G:i:s') <= Transaction::GOLD_POINT_PERIOD_END) {
248 $transactionConfig = $this->container->getParameter('transaction');
249 $validUntil = \DateTime::createFromFormat('Y-m-d', date('Y-m-d', $transactionConfig['voucher']['valid_until']));
250
251 $customerPoint = new CustomerPoint();
252 $customerPoint->setCustomer($customer)
253 ->setPoint($transaction->getPoint())
254 ->setContainer('transaction')
255 ->setContainerId($transaction->getId())
256 ->setDescription('Belanja di ORORI ('.date('d/m/y').') - '.$transaction->getId())
257 ->setValidUntil($validUntil)
258 ->setCreatedAt($this->timeInit)
259 ->setCreatedBy('SYSTEM')
260 ;
261
262 $lastCustomerPoint = $customer->getPoint();
263 $tempTransactionPoint = $transaction->getPoint();
264 $curCustomerPoint = $lastCustomerPoint + $tempTransactionPoint;
265
266 $customer->setPoint($curCustomerPoint);
267
268 // Upgrade customer level if point requirement meets
269 $recentTransaction = array('goldVal' => 0, 'nonGoldVal' => 0);
270 if ($details) {
271 foreach ($details as $detail) {
272 if (in_array($detail->getProduct()->getType(), Product::$listGoldPoint)) {
273 $recentTransaction['goldVal'] += $detail->getTotalPrice();
274 } else {
275 $recentTransaction['nonGoldVal'] += $detail->getTotalPrice();
276 }
277 }
278 }
279
280 $prevTransaction = $transactionRepo->fetchAllTransactionGoldPoint($customer->getId());
281 $prevLevel = $customer->getLevel() == 1 ?
282 'Silver' :
283 ($customer->getLevel() == 2 ? 'Gold' : ($customer->getLevel() == 3 ? 'Platinum' : ''));
284 $levelChanged = $prevLevel;
285 if (($prevTransaction['goldVal'] + $recentTransaction['goldVal']) >= Transaction::GOLD_POINT_LEVEL_S2G || ($prevTransaction['nonGoldVal'] + $recentTransaction['nonGoldVal']) >= Transaction::GOLD_POINT_LEVEL_S2G) {
286 $customer->setLevel(Customer::LEVEL_GOLD);
287 $levelChanged = 'Gold';
288 }
289 if (($prevTransaction['goldVal'] + $recentTransaction['goldVal']) >= Transaction::GOLD_POINT_LEVEL_G2P || ($prevTransaction['nonGoldVal'] + $recentTransaction['nonGoldVal']) >= Transaction::GOLD_POINT_LEVEL_G2P) {
290 $customer->setLevel(Customer::LEVEL_DIAMOND);
291 $levelChanged = 'Platinum';
292 }
293
294 if ($prevLevel != $levelChanged) {
295 try {
296 $this->get('gearman')->doBackgroundJob(
297 JobName::GOLDPOINT_LEVEL_UPGRADE_NOTIF, json_encode([
298 'name' => $customer->getFirstname(),
299 'email' => $customer->getEmail(),
300 'level' => $levelChanged,
301 'previous_level' => $prevLevel,
302 ]));
303 } catch (JobDoesNotExistException $e) {
304 $this->log($e);
305 } catch (WorkerDoesNotExistException $e) {
306 $this->log($e);
307 }
308 }
309 $this->em->persist($customerPoint);
310 $this->em->persist($customer);
311
312 $this->em->flush();
313
314 //if total point > 0, customer will get "email goldpoint"
315 if ($curCustomerPoint != 0) {
316
317 /* @var $pointRewardRepo \ORORI\CoreBundle\Repository\PointRewardRepository */
318 $pointRewardRepo = $this->em->getRepository('ORORICoreBundle:PointReward');
319 $pointReward = $pointRewardRepo->fetchAll(array(
320 'point' => $curCustomerPoint == 0 ? -1 : $curCustomerPoint,
321 'order_by' => 'point',
322 'order_type' => 'DESC',
323 'limit' => 2,
324 ));
325
326 //email goldpoint after checkout
327 $mailData = [
328 'header1' => 'HEADER 1',
329 'header2' => 'HEADER 2',
330 'lastCustomerPoint' => $lastCustomerPoint,
331 'tempTransactionPoint' => $tempTransactionPoint,
332 'curCustomerPoint' => $curCustomerPoint,
333 'email' => $customer->getEmail(),
334// 'email' => ['nisa.test123@gmail.com', 'istikhanah@orori.com'],
335// 'email' => ['kenanya.gusti@orori.com'],
336 ];
337
338 if (empty($pointReward)) {
339 $mailData['banner'] = '<img src="https://orori-telin.akamaized.net/images.orori.com/etc/email/Goldpoint_imageR-08-11-2016-11-33-35.jpg" style="width:100%;" />';
340 $mailData['isEnoughPointReward'] = false;
341 } else {
342 $mailData['banner'] = '<img src="https://orori-telin.akamaized.net/images.orori.com/etc/email/Goldpoint_imageR-08-11-2016-11-33-35.jpg" style="width:100%;" />';
343 $mailData['isEnoughPointReward'] = true;
344 $ii = 1;
345 foreach ($pointReward as $item) {
346 $mailData['reward']['name'.$ii] = $item['name'];
347 $mailData['reward']['description'.$ii] = $item['description'];
348 $mailData['reward']['point'.$ii] = $item['point'];
349 $mailData['reward']['image'.$ii] = $item['stock'] > 0 ? $item['image'] : '';
350 ++$ii;
351 }
352 $mailData['reward_counter'] = $ii - 1;
353 }
354
355// $subject = 'Selamat! Gold Point Anda Bertambah Menjadi '.$curCustomerPoint;
356 $subject = 'Selamat! Anda Mendapat '.$tempTransactionPoint.' Gold Point';
357 $body = $this->renderView('ORORIWorkerBundle:Mail:goldpoint-after-checkout.html.twig', $mailData);
358 $this->sendMail($mailData['email'], $subject, $body);
359 }
360 }
361 }
362
363 // Add stock on status cancel for cutable stock
364 // Pending -> Cancel
365 if ($post['transaction_status'] == Transaction::STATUS_CANCEL &&
366 $transaction->getStatus() == Transaction::STATUS_PENDING) {
367 $details = $transaction->getTransactionDetail();
368 $entityManager = $this->getDoctrine()->getManager();
369
370 $voucherRepo = $this->em->getRepository('ORORIVoucherBundle:Voucher');
371 $voucher = $voucherRepo->findOneBy(array('transaction' => $transaction));
372 if ($voucher) {
373 $voucher->setTimeOfUsed($voucher->getTimeOfUsed() + 1);
374 $entityManager->persist($voucher);
375 $entityManager->flush();
376 }
377
378 $paymentRepository = $entityManager->getRepository('ORORICoreBundle:Payment');
379 $payment = $paymentRepository->findOneBy(array('transaction' => $transaction));
380 if ($payment) {
381 $payment->setStatus(Payment::STATUS_ERROR);
382 $entityManager->persist($payment);
383 $entityManager->flush();
384 }
385
386 if ($details) {
387 foreach ($details as $detail) {
388 $prod = $detail->getProduct();
389 $qty = $detail->getCount();
390
391 if ((in_array($prod->getType(), [
392 Product::TYPE_BOX,
393 Product::TYPE_CLEANING,
394 Product::TYPE_GOLDJEWELRY,
395 Product::TYPE_UBS_FASHION,
396 Product::TYPE_UBS_GOLD,
397 Product::TYPE_UBS_PROMO,
398 Product::TYPE_UBS_MENSRING,
399 Product::TYPE_UBS_WOMENSRING,
400 Product::TYPE_GOLD,
401 Product::TYPE_UPLOAD,
402 ])
403 || $productRepo->isFlashSaleProduct($prod)
404 || $prod->getIsCuttingStock())
405 && $prod->getCategory() !== Product::CATEGORY_GOLD_PENDANT_ALPHABET
406 && $prod->getType() !== Product::TYPE_GOLD
407 ) {
408 $currentQty = $prod->getQuantity();
409 $prod->addQuantity($qty);
410
411 $infoMerchandising = true;
412 $infoProducts[] = '<img src="'.$prod->getMainImage().'" style="width:200px;" /><br />'.$prod->getCode()
413 .' from '.$currentQty.' to '.$prod->getQuantity();
414
415 $this->em->persist($prod);
416 // Save to table_modify before flush to make this work
417 $this->logModified($prod, 'TRANSACTION CANCEL '.$transaction->getId());
418 $this->em->flush();
419 }
420 }
421 }
422 }
423
424 // Reduce stock on status pending from cancel for flash sale product only
425 // Cancel -> Pending || Cancel -> Processing
426 if (($post['transaction_status'] == Transaction::STATUS_PENDING &&
427 $transaction->getStatus() == Transaction::STATUS_CANCEL) ||
428 ($post['transaction_status'] == Transaction::STATUS_SUPPLIER &&
429 $transaction->getStatus() == Transaction::STATUS_CANCEL)) {
430 $details = $transaction->getTransactionDetail();
431
432 if ($details) {
433 foreach ($details as $detail) {
434 $prod = $detail->getProduct();
435 $qty = $detail->getCount();
436
437 // Only for flashsale product
438 if ((in_array($prod->getType(), $productRepo->getCuttingStockType())
439 || $productRepo->isFlashSaleProduct($prod)
440 || $prod->getIsCuttingStock())
441 && $prod->getCategory() !== Product::CATEGORY_GOLD_PENDANT_ALPHABET
442 ) {
443 $deduction = -1 * $qty;
444 $currentQty = $prod->getQuantity();
445
446 $prod->addQuantity($deduction);
447
448 $infoMerchandising = true;
449 $infoProducts[] = '<img src="'.$prod->getMainImage().'" style="width:200px;" /><br />'.$prod->getCode()
450 .' from '.$currentQty.' to '.$prod->getQuantity();
451
452 $this->em->persist($prod);
453 // Save to table_modify before flush to make this work
454 $this->logModified($prod, 'TRANSACTION PROCESSING '.$transaction->getId());
455 $this->em->flush();
456 }
457 }
458 }
459
460 if ($post['transaction_status'] === Transaction::STATUS_SUPPLIER) {
461 if (date('Y-m-d G:i:s') >= Transaction::GOLD_POINT_PERIOD_START && date('Y-m-d G:i:s') <= Transaction::GOLD_POINT_PERIOD_END) {
462 $customer = $transaction->getCustomer();
463 $customerPoint = new CustomerPoint();
464 $customerPoint->setCustomer($customer)
465 ->setPoint($transaction->getPoint())
466 ->setContainer('transaction')
467 ->setContainerId($transaction->getId())
468 ->setDescription('Pesanan sedang diproses ('.date('d/m/y').') - '.$transaction->getId())
469 ->setValidUntil(\DateTime::createFromFormat('Y-m-d', date('Y-m-d')))
470 ->setCreatedAt($this->timeInit)
471 ->setCreatedBy('SYSTEM')
472 ;
473 $customer->setPoint($customer->getPoint() - $transaction->getPoint());
474 $this->em->persist($customerPoint);
475 $this->em->persist($customer);
476 $this->em->flush();
477 }
478 }
479 }
480
481 // Add stock on status cancel
482 // Processing -> Cancel
483 if ($post['transaction_status'] == Transaction::STATUS_CANCEL &&
484 $transaction->getStatus() == Transaction::STATUS_SUPPLIER) {
485 $customer = $transaction->getCustomer();
486 $details = $transaction->getTransactionDetail();
487
488 $entityManager = $this->getDoctrine()->getManager();
489
490 $voucherRepo = $this->em->getRepository('ORORIVoucherBundle:Voucher');
491 $voucher = $voucherRepo->findOneBy(array('transaction' => $transaction));
492 if ($voucher) {
493 $voucher->setTimeOfUsed($voucher->getTimeOfUsed() + 1);
494 $entityManager->persist($voucher);
495 $entityManager->flush();
496 }
497
498 $paymentRepository = $entityManager->getRepository('ORORICoreBundle:Payment');
499 $payment = $paymentRepository->findOneBy(array('transaction' => $transaction));
500 if ($payment) {
501 $payment->setStatus(Payment::STATUS_ERROR);
502 $entityManager->persist($payment);
503 $entityManager->flush();
504 }
505
506 $voucherManager = new VoucherManager();
507
508 if ($details) {
509 foreach ($details as $detail) {
510 $prod = $detail->getProduct();
511 $qty = $detail->getCount();
512
513 $voucherManager->addProduct($prod, $productRepo->getFrontendEntityData($prod), $detail->getCount());
514
515 // Only for goldjewelry product, cleaning, box, diamondjewelry
516 if ((in_array($prod->getType(), [
517 Product::TYPE_BOX,
518 Product::TYPE_CLEANING,
519 Product::TYPE_GOLDJEWELRY,
520 Product::TYPE_UBS_FASHION,
521 Product::TYPE_UBS_GOLD,
522 Product::TYPE_UBS_PROMO,
523 Product::TYPE_UBS_MENSRING,
524 Product::TYPE_UBS_WOMENSRING,
525 Product::TYPE_GOLD,
526 Product::TYPE_UPLOAD,
527 ])
528 || $productRepo->isFlashSaleProduct($prod)
529 || $prod->getIsCuttingStock())
530 && $prod->getCategory() !== Product::CATEGORY_GOLD_PENDANT_ALPHABET
531 && $prod->getType() !== Product::TYPE_GOLD
532 ) {
533 $currentQty = $prod->getQuantity();
534
535 $prod->addQuantity($qty);
536
537 $infoMerchandising = true;
538 $infoProducts[] = '<img src="'.$prod->getMainImage().'" style="width:200px;" /><br />'.$prod->getCode()
539 .' from '.$currentQty.' to '.$prod->getQuantity();
540 }
541 $this->em->persist($prod);
542 // Save to table_modify before flush to make this work
543 $this->logModified($prod, 'TRANSACTION CANCEL '.$transaction->getId());
544 $this->em->flush();
545 }
546 }
547
548 /**
549 * Referral Customer
550 */
551 $logger = $this->get('monolog.logger.payment_channel');
552 $customerReferral = $this->get('doctrine.orm.entity_manager')->getRepository('ORORICoreBundle:Customer')->findOneBy(array('uniqueCode' => $transaction->getVoucherCode()));
553 if ($customerReferral) {
554 $logger->info('[REFERRAL] Customer Unique Code'.$customerReferral->getUniqueCode());
555 $logger->info('[REFERRAL] Voucher Code'.$transaction->getVoucherCode());
556 if (strtoupper($transaction->getVoucherCode()) === strtoupper($customerReferral->getUniqueCode()) && $voucherManager->isReferralVoucher($transaction->getVoucherCode())) {
557 $logger = $this->get('monolog.logger.payment_channel');
558 $logger->info('[REFERRAL APPLIED]');
559 $point = $voucherManager->getTotalPoint();
560 $logger->info('[REFERRAL POINT] '.$point);
561 if ($customerReferral) {
562 $customerPoint = new CustomerPoint();
563 $customerPoint->setCustomer($customerReferral)
564 ->setPoint('-'.$point)
565 ->setContainer('transaction')
566 ->setContainerId($transaction->getId())
567 ->setDescription('Pembatalan Pesanan ('.date('d/m/y').') - '.$transaction->getId())
568 ->setValidUntil(\DateTime::createFromFormat('Y-m-d', date('Y-m-d')))
569 ->setCreatedAt($this->timeInit)
570 ->setCreatedBy('SYSTEM')
571 ;
572 $customerReferral->setPoint($customerReferral->getPoint() - $point);
573 $this->em->persist($customerPoint);
574 $this->em->persist($customerReferral);
575 }
576 }
577 }
578
579 $this->em->flush();
580
581 //revoke gold point
582 if (date('Y-m-d G:i:s') >= Transaction::GOLD_POINT_PERIOD_START && date('Y-m-d G:i:s') <= Transaction::GOLD_POINT_PERIOD_END) {
583 $customerPoint = new CustomerPoint();
584 $customerPoint->setCustomer($customer)
585 ->setPoint('-'.$transaction->getPoint())
586 ->setContainer('transaction')
587 ->setContainerId($transaction->getId())
588 ->setDescription('Pembatalan Pesanan ('.date('d/m/y').') - '.$transaction->getId())
589 ->setValidUntil(\DateTime::createFromFormat('Y-m-d', date('Y-m-d')))
590 ->setCreatedAt($this->timeInit)
591 ->setCreatedBy('SYSTEM')
592 ;
593 $customer->setPoint($customer->getPoint() - $transaction->getPoint());
594 $this->em->persist($customerPoint);
595 $this->em->persist($customer);
596 }
597 }
598
599 if ($post['transaction_status'] == Transaction::STATUS_DELIVERED) {
600 $deliveryDate = empty($post['delivery_date']) ? new \DateTime() : \DateTime::createFromFormat('Y-m-d', $post['delivery_date']);
601 $transaction->setDeliveryDate($deliveryDate);
602
603 $this->sendOrderReviewEmail($transaction);
604 }
605
606 $transaction->setStatus($post['transaction_status'])
607 ->setUpdatedBy($user->getUsername());
608
609 if (isset($post['notify_customer'])) {
610 $new->setNotifyCustomer($post['notify_customer']);
611 }
612 if (!empty($post['comment'])) {
613 $new->setComment($post['comment']);
614 }
615
616 if ($post['transaction_status'] == Transaction::STATUS_SAVING || $transaction->getStatus() == Transaction::STATUS_SAVING) {
617 $orobox = $this->em->getRepository('ORORI\GoldDepositBundle\Entity\GoldDeposit')->findBy(array('transaction_id'=>$transaction->getId()));
618 $oroboxActive = false;
619
620 if ($post['transaction_status'] == Transaction::STATUS_SAVING && $transaction->getStatus() != Transaction::STATUS_SAVING) {
621 $oroboxActive = true;
622 }
623
624 foreach ($orobox as $goldDeposit) {
625 $goldDeposit->setIsActive($oroboxActive);
626 $this->em->persist($goldDeposit);
627 }
628 }
629
630 $this->createVoucherPromo($post['transaction_status'], $transaction);
631
632 // Insert transaction history
633 $this->em->persist($transaction);
634 $this->em->persist($new);
635 $this->em->flush();
636 $data = $transHistoryRepo->getEntityData($new);
637
638 // Send notification
639 if (!empty($post['notify_customer'])) {
640 $comment = empty($post['comment']) ? '' : $post['comment'];
641 $this->sendNotificationToCustomer($transaction, $comment);
642 }
643
644 // Send notification
645 if ($infoMerchandising) {
646 $this->sendNotificationToMerchandising($transaction, $infoProducts);
647 }
648
649 return $this->successResponse(array(
650 'transaction_history' => $data,
651 ), HttpStatus::HTTP_CREATED);
652 }
653
654 private function createVoucherPromo($status, $transaction){
655 // code by jacky : promo voucher utk special pick
656 if ($status == Transaction::STATUS_SUPPLIER){
657 $voucherRepo = $this->em->getRepository('ORORIVoucherBundle:Voucher');
658 $promoRepo = $this->em->getRepository('ORORICoreBundle:Promo');
659 $productRepo = $this->em->getRepository('ORORICoreBundle:Product');
660 $promoVoucher = $promoRepo->getPromoVoucher();
661 $hasPromo = false;
662
663 foreach ($transaction->getTransactionDetail() as $detail){
664 $productDetail = $detail->getProduct();
665 if (isset($promoVoucher) && is_array($promoVoucher) && !empty($promoVoucher)) {
666 foreach ($promoVoucher as $name => $rules) {
667 if ($promoRepo->checkPromoVoucher($productRepo->getEntityData($productDetail), $name, $rules)){
668 $voucherRule = $rules['voucher']['rule'];
669 $prefix = $rules['voucher']['prefix'];
670 $desc = $rules['voucher']['desc'];
671 $customer = null;
672 $validUntil = '';
673 $category = [];
674 $value = 0;
675 $minPrice = 0;
676
677 if ('true' === $rules['voucher']['customer'] || '1' === $rules['voucher']['customer'] || 1 === $rules['voucher']['customer']) {
678 $rules['voucher']['customer'] = true;
679 }
680 else {
681 $rules['voucher']['customer'] = false;
682 }
683
684 if ($rules['voucher']['customer']) {
685 $customer = $transaction->getCustomer();
686 }
687
688 if ('custom' === $rules['voucher']['rule']) {
689 $value = $rules['voucher']['value'];
690 $minPrice = $rules['voucher']['min_price'];
691 }
692
693 $voucher = $voucherRepo->generateFreeVoucher($voucherRule, $prefix, $desc, $customer, $validUntil, $category, $value, $minPrice);
694 $customer = $transaction->getCustomer();
695
696 $this->get('gearman')->doBackgroundJob(
697 \ORORI\CoreBundle\Gearman\JobName::FLASHSALE_VOUCHER_NOTIF, json_encode([
698 'email' => $customer->getEmail(),
699 'name' => $customer->getFirstname() .' '. $customer->getLastname(),
700 'voucher_code' => $voucher->getCode(),
701 'voucher_value' => $voucher->getValue(),
702 'voucher_prod' => $productDetail->getCode(),
703 'voucher_minPrice' => $voucher->getMinimumPrice()
704 //'voucher_type' => $voucher->getType(),
705 //'voucher_valid_until' => $voucher->getValidUntil(),
706 ]));
707
708 $hasPromo = true;
709
710 break;
711 }
712 }
713 }
714 }
715
716 return $hasPromo;
717 }
718 return false;
719 }
720
721 /**
722 * Validate create parameter.
723 *
724 * @param \Symfony\Component\HttpFoundation\Request $req
725 *
726 * @return bool | \Symfony\Component\HttpFoundation\JsonResponse
727 */
728 private function validateCreateParameter(Request $req)
729 {
730 $post = $req->request->all();
731
732 if (!isset($post['transaction_status'])) {
733 return $this->errorResponse(
734 $this->translator->trans('error.required', array('%s%' => $this->translator->trans('transaction_status')))
735 );
736 }
737
738 return true;
739 }
740
741 /**
742 * Send email for each status update.
743 *
744 * @param Transaction $transaction
745 * @param string $comment
746 *
747 * @return mixed
748 */
749 private function sendNotificationToCustomer(Transaction $transaction, $comment)
750 {
751 $data = new \stdClass();
752 $data->header1 = 'ORDER UPDATE '.$transaction->getTransactionNo().' '.strtoupper($transaction->getStatusInString());
753 $data->header2 = $transaction->getTransactionNo();
754 $data->customer_name = trim($transaction->getCustomer()->getFirstname());
755 $data->customer_email = trim($transaction->getCustomer()->getEmail());
756 $data->transaction_no = $transaction->getTransactionNo();
757 $data->no_layout = true;
758 $data->content = $comment;
759 $bcc = $transaction->getStatus() == Transaction::STATUS_DELIVERED ?
760 'system_8d101a0ee4615@inbound.trustedcompany.com' : null;
761
762 $subject = 'Update on order number '.$transaction->getTransactionNo();
763 $body = $this->renderView('ORORIWorkerBundle:Mail:blank-with-layout.html.twig', (array) $data);
764
765 return $this->sendMail($transaction->getCustomer()->getEmail(), $subject, $body, null, 'ORORI Jewelry', $bcc);
766 }
767
768 /**
769 * Send email to merchandising head for info.
770 *
771 * @param Transaction $transaction
772 * @param array $productInfo
773 *
774 * @return mixed
775 */
776 private function sendNotificationToMerchandising(Transaction $transaction, array $productInfo)
777 {
778 $data = new \stdClass();
779 $data->header1 = '[Notification] Product quantity update from transaction ';
780 $data->header2 = $transaction->getTransactionNo();
781 $data->content = implode('<br />', $productInfo);
782
783 $subject = '[Notification] Product quantity update from transaction '.$transaction->getTransactionNo();
784 $body = $this->renderView('ORORIWorkerBundle:Mail:blank.html.twig', (array) $data);
785
786 return $this->sendMail(['sales.team@orori.com', 'irwan.j@orori.com'], $subject, $body);
787 }
788
789 private function sendEmailToSupplier(Transaction $transaction, \ORORI\CoreBundle\Entity\Supplier $supplier)
790 {
791 if ($supplier->getEmail()) {
792 $transactionRepo= $this->em->getRepository('ORORICoreBundle:Transaction');
793 $data = $transactionRepo->getEmailData($transaction);
794 $data->merchant = ucwords(strtolower($supplier->getName()));
795
796 $subject = 'New Order Marketplace ORORI.com';
797 $body = $this->renderView('ORORIWorkerBundle:Mail:order-confirmation-supplier.html.twig', (array) $data);
798
799 // Mail to sales
800 $this->sendMail($supplier->getEmail(), $subject, $body);
801// $this->sendMail('ihsan@orori.com', $subject, $body);
802 }
803 }
804
805 /**
806 * Send an order review email
807 * Add cc to Trusted Company system email
808 * Because in bcc isn't working.
809 *
810 * @param Transaction $transaction
811 *
812 * @return bool
813 */
814 private function sendOrderReviewEmail(Transaction $transaction)
815 {
816 //--------------------------- new ----------------------------------------------
817 $customer = $transaction->getCustomer();
818 $cust_name = $customer->getFirstname().' '.$customer->getLastname();
819 $mailData = [
820 'header1' => 'HEADER 1',
821 'header2' => 'HEADER 2',
822 'created_at' => $transaction->getCreatedAt(),
823 'cust_name' => $cust_name,
824 'trans_no' => $transaction->getTransactionNo(),
825 'trans_id' => $transaction->getId(),
826 'link_review' => 'https://www.orori.com/order-review?tid='.$transaction->getTransactionNo(),
827 'email' => [$customer->getEmail()],
828 'cid' => $this->genUUID(),
829 ];
830
831 $subject = 'Tambahan Diskon 5% + 10 Gold Point Hanya untuk '.$cust_name;
832 $body = $this->renderView('ORORIWorkerBundle:Mail:mail-review-request-1.html.twig', $mailData);
833
834// $mailConfig = $this->container->getParameter('mailfrom');
835// $awsConfig = $this->container->getParameter('aws');
836// $sesClient = SesClient::factory(array(
837// 'key' => $awsConfig['key'],
838// 'secret' => $awsConfig['secret'],
839// 'region' => $awsConfig['ses']['region'],
840// ));
841//
842//// $mailConfig['bcc'] += $bcc;
843//
844// $message = new \Swift_Message();
845// $message->setFrom($mailConfig['noreply'], 'ORORI Jewelry')
846// ->setTo($mailData['email'])
847// ->setCc([
848// 'system_8d101a0ee4615@inbound.trustedcompany.com',
849// ])
850// ->setSubject($subject)
851// ->setBody($body, 'text/html')
852// ;
853//
854// foreach ($mailConfig['bcc'] as $row) {
855// $message->addBcc($row);
856// }
857//
858// $sesClient->sendRawEmail(array(
859// 'RawMessage' => array(
860// 'Data' => base64_encode($message->toString()),
861// ),
862// ));
863//
864// return true;
865 return $this->sendMail($mailData['email'], $subject, $body, null, 'ORORI Jewelry', 'system_8d101a0ee4615@inbound.trustedcompany.com');
866 }
867
868 private function genUUID()
869 {
870 return sprintf(
871 '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
872 mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
873 mt_rand( 0, 0xffff ),
874 mt_rand( 0, 0x0fff ) | 0x4000,
875 mt_rand( 0, 0x3fff ) | 0x8000,
876 mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
877 );
878 }
879}