· 8 years ago · Jan 16, 2017, 05:08 AM
1<?php
2
3namespace ORORI\ApiBundle\Controller\Transaction;
4
5use Mmoreram\GearmanBundle\Exceptions\JobDoesNotExistException;
6use Mmoreram\GearmanBundle\Exceptions\WorkerDoesNotExistException;
7use Nelmio\ApiDocBundle\Annotation\ApiDoc;
8use ORORI\ApiBundle\Controller\BaseController;
9use ORORI\CoreBundle\Entity\Customer;
10use ORORI\CoreBundle\Entity\CustomerPoint;
11use ORORI\CoreBundle\Entity\OauthToken;
12use ORORI\CoreBundle\Entity\Payment;
13use ORORI\CoreBundle\Entity\Product;
14use ORORI\CoreBundle\Entity\Transaction;
15use ORORI\CoreBundle\Entity\TransactionDetail;
16use ORORI\CoreBundle\Gearman\JobName;
17use ORORI\CoreBundle\Helper\Country;
18use ORORI\CoreBundle\Helper\HttpStatusHelper as HttpStatus;
19use ORORI\CoreBundle\Helper\Sodexo;
20use ORORI\PaymentBundle\Adapter\Handler\BaseDirectPaymentHandler;
21use ORORI\PaymentBundle\Adapter\Handler\BaseRedirectPaymentHandler;
22use ORORI\PaymentBundle\Adapter\Handler\BaseTwoStepPaymentHandler;
23use ORORI\PaymentBundle\Adapter\Handler\EPayBri;
24use ORORI\PaymentBundle\Adapter\PaymentHandlerFactory;
25use ORORI\PaymentBundle\Adapter\PaymentOptionFactory;
26use ORORI\VoucherBundle\Entity\Voucher;
27use ORORI\VoucherBundle\Manager\VoucherManager;
28use Symfony\Component\HttpFoundation\JsonResponse;
29use Symfony\Component\HttpFoundation\Request;
30use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
31use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
32use Symfony\Component\HttpFoundation\ResponseHeaderBag;
33use Symfony\Component\HttpFoundation\StreamedResponse;
34
35class OrderController extends BaseController
36{
37 private $curBuy1Get1;
38 private $curBuy1DiscOther;
39
40 /**
41 * @ApiDoc(
42 * section="Frontend",
43 * resource="Shopping Cart",
44 * description="Checkout proccess",
45 * parameters={
46 * {"name"="access_token", "dataType"="string", "required"=true, "description"="Customer or User access token"},
47 * {"name"="billing_data[firstname]", "dataType"="array", "required"=true, "description"="billing first name"},
48 * {"name"="billing_data[lastname]", "dataType"="array", "required"=true, "description"="billing last name"},
49 * {"name"="billing_data[address]", "dataType"="array", "required"=true, "description"="billing address"},
50 * {"name"="billing_data[country]", "dataType"="array", "required"=true, "description"="billing country"},
51 * {"name"="billing_data[province]", "dataType"="array", "required"=true, "description"="billing province"},
52 * {"name"="billing_data[city]", "dataType"="array", "required"=true, "description"="billing city"},
53 * {"name"="billing_data[zipcode]", "dataType"="array", "required"=true, "description"="billing zipcode"},
54 * {"name"="billing_data[telephone]", "dataType"="array", "required"=false, "description"="billing telephone"},
55 * {"name"="customer_data[firstname]", "dataType"="array", "required"=true, "description"="customer first name"},
56 * {"name"="customer_data[lastname]", "dataType"="array", "required"=true, "description"="customer last name"},
57 * {"name"="customer_data[address]", "dataType"="array", "required"=true, "description"="customer address"},
58 * {"name"="customer_data[city]", "dataType"="array", "required"=true, "description"="customer city"},
59 * {"name"="customer_data[province]", "dataType"="array", "required"=true, "description"="customer province"},
60 * {"name"="customer_data[country]", "dataType"="array", "required"=true, "description"="customer country"},
61 * {"name"="customer_data[zipcode]", "dataType"="array", "required"=true, "description"="customer zipcode"},
62 * {"name"="customer_data[telephone]", "dataType"="array", "required"=false, "description"="customer telephone"},
63 * {"name"="delivery_data[firstname]", "dataType"="array", "required"=true, "description"="receiver first name"},
64 * {"name"="delivery_data[lastname]", "dataType"="array", "required"=true, "description"="receiver last name"},
65 * {"name"="delivery_data[address]", "dataType"="array", "required"=true, "description"="receiver address"},
66 * {"name"="delivery_data[city]", "dataType"="array", "required"=true, "description"="receiver city"},
67 * {"name"="delivery_data[province]", "dataType"="array", "required"=true, "description"="receiver province"},
68 * {"name"="delivery_data[country]", "dataType"="array", "required"=true, "description"="receiver country"},
69 * {"name"="delivery_data[zipcode]", "dataType"="array", "required"=true, "description"="receiver zipcode"},
70 * {"name"="delivery_data[telephone]", "dataType"="array", "required"=false, "description"="receiver telephone"},
71 * {"name"="shopping_cart", "dataType"="string", "required"=true, "description"="Shopping cart ID, comma separated for multiple values"},
72 * {"name"="payment_method", "dataType"="integer", "required"=true, "format"="1|2|3|4|5|6|7|8|9",
73 * "description"="1=transfer,2=CC,3=BCA 3 bln,4=cimb click,5=klikbca,6=bca klikpay,7=mandiri clickpay,8=mandiri sms banking,9=EDC"},
74 * {"name"="shipping_company", "dataType"="string", "required"=true, "format"="0|1|11|12|13|14|16|17|18|19",
75 * "description"="0=courier, 1=jne regular, 2=jne yes, 3=jne oke, 4=jne sps, 11=rpx ecp, 12=rpx ndp, 13=rpx mdp, 14=rpx sdp, 16=rpx ecp insurance, 17=rpx ndp insurance, 18=rpx mdp insurance, 19=rpx sdp insurance"},
76 * {"name"="shipping_fee", "dataType"="float", "required"=false, "description"="Shipping cost"},
77 * {"name"="unique_code", "dataType"="string", "required"=false, "description"="Unique code for bank transfer"},
78 * {"name"="voucher_code", "dataType"="string", "required"=false, "description"="Voucher code to get extra discount"},
79 * {"name"="goldpoint", "dataType"="int", "required"=false, "description"="Customer's goldpoint that will be used for more discount"},
80 * {"name"="ga_utm", "dataType"="string", "required"=false, "description"="utm for transaction"},
81 * {"name"="country", "dataType"="string", "required"=false, "format"="sg|id",
82 * "description"="country code, using ISO 639-1, default = id"},
83 * {"name"="lang", "dataType"="string", "required"=false, "format"="en|id",
84 * "description"="response language, using ISO 639-1, default = id"},
85 * {"name"="shoppingcart_meta", "dataType"="array", "required"=false, "description"="Meta are determined by payment method:
86 If payment method is klikbca, shoppingcart_meta=['klikbca_id' => 'customer_klikbca_id'].
87 If payment method is mandiri sms, shoppingcart_meta = ['phone_no' => 'customer_phone_no'].
88 If payment method is bca klikpay, shoppingcart_meta=[ [ 'shoppingcart_id' : 'shoppingcart_id_1', 'tenor' => 'tenor_payment_1'], [ 'shoppingcart_id' : 'shoppingcart_id_2', 'tenor' => 'tenor_payment_2'], ...]
89 * "}
90 * },
91 * statusCodes={
92 * 201="Returned when successful",
93 * 400="Bad request",
94 * 401="Unauthorized",
95 * 404="Not found",
96 * 500="System error",
97 * }
98 * )
99 */
100 public function createAction(Request $req)
101 {
102 $post = $req->request->all();
103 $this->init($post);
104
105 // Validate parameter sent
106 $valid = $this->validateCreateParameter($req);
107 if ($valid instanceof JsonResponse) {
108 return $valid;
109 }
110
111 // Validate access token
112 $token = $this->validateAccessToken($req);
113 if (!$token instanceof OauthToken) {
114 return $token;
115 }
116
117 $customer = $token->getCustomer();
118 $post['creator'] = $customer->getUsername();
119
120 return $this->createOrder($post, $customer, $customer->getUsername());
121 }
122
123 /**
124 * @ApiDoc(
125 * section="Master",
126 * resource="Transaction",
127 * description="Download Shipping Order CSV",
128 * parameters={
129 * {"name"="access_token", "dataType"="string", "required"=true, "description"="User access token"},
130 * {"name"="date", "dataType"="date", "required"=false, "format"="Y-m-d", "description"="Deadline date"},
131 * },
132 * statusCodes={
133 * 200="Returned when successful",
134 * 400="Bad request",
135 * 401="Unauthorized",
136 * 500="System error",
137 * }
138 * )
139 * @Security("has_role('ROLE_ORDER_DEADLINE_CSV')")
140 */
141 public function deadlineCsvAction(Request $req)
142 {
143 $get = $req->query->all();
144 $this->init($get);
145
146 // Validate access token
147 $token = $this->validateAccessToken($req);
148 if (!$token instanceof OauthToken) {
149 return $token;
150 }
151
152 $date = empty($get['date']) ? new \DateTime() : \DateTime::createFromFormat('Y-m-d', $get['date']);
153
154 /* @var $transactionRepo \ORORI\CoreBundle\Repository\TransactionRepository */
155 $transactionRepo = $this->em->getRepository('ORORICoreBundle:Transaction');
156 $queryBuilder = $transactionRepo->createQueryBuilder('t')
157 ->select('t, c')
158 ->join('t.customer', 'c')
159 ->where('t.deadline >= :start')
160 ->andWhere('t.deadline <= :end')
161 ->setParameter(':start', $date->format('Y-m-d').' 00:00:00')
162 ->setParameter(':end', $date->format('Y-m-d').' 23:59:59')
163 ;
164
165 $query = $queryBuilder->getQuery();
166 $query->useQueryCache(true);
167 $query->useResultCache(true, 15, sprintf('%s_%s_%s', __CLASS__, __METHOD__, serialize($query->getParameters()->toArray())));
168 $transactions = $query->getResult();
169
170 $objPHPExcel = new \PHPExcel();
171 $row = 1;
172 $objPHPExcel->getActiveSheet()->setCellValue('A'.$row, 'ID')
173 ->setCellValue('B'.$row, 'Nama')
174 ->setCellValue('C'.$row, 'Alamat')
175 ->setCellValue('D'.$row, 'Telepon')
176 ->setCellValue('E'.$row, 'URL')
177 ;
178 ++$row;
179
180 foreach ($transactions as $rs) {
181 $ship = $rs->getDeliveryData();
182
183 if ($rs->getShippingCompany() === Transaction::SHIPPING_POPBOX) {
184 $shippingAddress = 'popbox';
185 $shippingAddress .= empty($ship->city) ? '' : ' '.$ship->city;
186 } else {
187 $shippingAddress = $ship->address;
188 $shippingAddress .= empty($ship->city) ? '' : ' '.$ship->city;
189 $shippingAddress .= empty($ship->province) ? '' : ' '.$ship->province;
190 $shippingAddress .= empty($ship->zipcode) ? '' : ', '.$ship->zipcode;
191 }
192
193 $objPHPExcel->getActiveSheet()->setCellValue('A'.$row, $rs->getId())
194 ->setCellValue('B'.$row, $ship->firstname.' '.$ship->lastname)
195 ->setCellValue('C'.$row, $shippingAddress)
196 ->setCellValueExplicit('D'.$row, $rs->getCustomer()->getTelephone())
197 ->setCellValue('E'.$row, 'https://www.orori.com/')
198 ;
199 ++$row;
200 }
201
202 $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'CSV');
203
204 $streamResponse = new StreamedResponse(function () use ($objWriter) {
205 return $objWriter->save('php://output');
206 });
207
208 $dispositionHeader = $streamResponse->headers->makeDisposition(
209 ResponseHeaderBag::DISPOSITION_ATTACHMENT,
210 'deadline.csv'
211 );
212
213// $streamResponse->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
214 $streamResponse->headers->set('Content-Type', 'text/csv');
215 $streamResponse->headers->set('Pragma', 'public');
216 $streamResponse->headers->set('Cache-Control', 'maxage=1');
217 $streamResponse->headers->set('Content-Disposition', $dispositionHeader);
218
219 return $streamResponse;
220 }
221
222 /**
223 * Validate create parameter.
224 *
225 * @param \Symfony\Component\HttpFoundation\Request $req
226 *
227 * @return bool | \Symfony\Component\HttpFoundation\JsonResponse
228 */
229 private function validateCreateParameter(Request $req)
230 {
231 $post = $req->request->all();
232
233 if (empty($post['shopping_cart'])) {
234 return $this->errorResponse(
235 $this->translator->trans(
236 'error.required',
237 array(
238 '%s%' => 'shopping cart',
239 )
240 )
241 );
242 }
243
244 if (empty($post['customer_data']['firstname'])) {
245 return $this->errorResponse(
246 $this->translator->trans(
247 'error.required',
248 array(
249 '%s%' => 'customer: '.$this->translator->trans('firstname'),
250 )
251 )
252 );
253 }
254
255 if (empty($post['customer_data']['address'])) {
256 return $this->errorResponse(
257 $this->translator->trans(
258 'error.required',
259 array(
260 '%s%' => 'customer: '.$this->translator->trans('address'),
261 )
262 )
263 );
264 }
265
266 if (empty($post['customer_data']['city'])) {
267 return $this->errorResponse(
268 $this->translator->trans(
269 'error.required',
270 array(
271 '%s%' => 'customer: '.$this->translator->trans('city'),
272 )
273 )
274 );
275 }
276
277 if (empty($post['customer_data']['province'])) {
278 return $this->errorResponse(
279 $this->translator->trans(
280 'error.required',
281 array(
282 '%s%' => 'customer: '.$this->translator->trans('province'),
283 )
284 )
285 );
286 }
287
288 if (empty($post['customer_data']['country'])) {
289 return $this->errorResponse(
290 $this->translator->trans(
291 'error.required',
292 array(
293 '%s%' => 'customer: '.$this->translator->trans('country'),
294 )
295 )
296 );
297 }
298
299 if (!Country::isExist($post['customer_data']['country'])) {
300 return $this->errorResponse(
301 $this->translator->trans(
302 'error.not_valid',
303 array(
304 '%s%' => 'customer: '.$this->translator->trans('country'),
305 )
306 )
307 );
308 }
309
310 if (empty($post['customer_data']['zipcode'])) {
311 return $this->errorResponse(
312 $this->translator->trans(
313 'error.required',
314 array(
315 '%s%' => 'customer: '.$this->translator->trans('zipcode'),
316 )
317 )
318 );
319 }
320
321 if (empty($post['delivery_data']['firstname'])) {
322 return $this->errorResponse(
323 $this->translator->trans(
324 'error.required',
325 array(
326 '%s%' => 'delivery: '.$this->translator->trans('firstname'),
327 )
328 )
329 );
330 }
331
332 if (empty($post['delivery_data']['address'])) {
333 return $this->errorResponse(
334 $this->translator->trans(
335 'error.required',
336 array(
337 '%s%' => 'delivery: '.$this->translator->trans('address'),
338 )
339 )
340 );
341 }
342
343 if (empty($post['delivery_data']['city'])) {
344 return $this->errorResponse(
345 $this->translator->trans(
346 'error.required',
347 array(
348 '%s%' => 'delivery: '.$this->translator->trans('city'),
349 )
350 )
351 );
352 }
353
354 if (empty($post['delivery_data']['province'])) {
355 return $this->errorResponse(
356 $this->translator->trans(
357 'error.required',
358 array(
359 '%s%' => 'delivery: '.$this->translator->trans('province'),
360 )
361 )
362 );
363 }
364
365 if (empty($post['delivery_data']['country'])) {
366 return $this->errorResponse(
367 $this->translator->trans(
368 'error.required',
369 array(
370 '%s%' => 'delivery: '.$this->translator->trans('country'),
371 )
372 )
373 );
374 }
375
376 if (!Country::isExist($post['delivery_data']['country'])) {
377 return $this->errorResponse(
378 $this->translator->trans(
379 'error.not_valid',
380 array(
381 '%s%' => 'delivery: '.$this->translator->trans('country'),
382 )
383 )
384 );
385 }
386
387 if (empty($post['delivery_data']['zipcode'])) {
388 return $this->errorResponse(
389 $this->translator->trans(
390 'error.required',
391 array(
392 '%s%' => 'delivery: '.$this->translator->trans('zipcode'),
393 )
394 )
395 );
396 }
397
398 if (empty($post['payment_method'])) {
399 return $this->errorResponse(
400 $this->translator->trans(
401 'error.required',
402 array(
403 '%s%' => $this->translator->trans('payment method'),
404 )
405 )
406 );
407 }
408
409 $validPaymentMethods = [
410 Payment::TYPE_TRANSFER,
411 Payment::TYPE_VISAMASTER,
412 Payment::TYPE_BCA_3_MONTH,
413 Payment::TYPE_CIMB_CLICK,
414 Payment::TYPE_KLIKBCA,
415 Payment::TYPE_BCA_KLIKPAY,
416 Payment::TYPE_MANDIRI_CLICKPAY,
417 Payment::TYPE_MANDIRI_SMSBANK,
418 Payment::TYPE_MOBILE_EDC,
419 Payment::TYPE_BNI_ECOLLECTION,
420 Payment::TYPE_KREDIVO,
421 Payment::TYPE_PERMATA_VA,
422 Payment::TYPE_MANDIRI_VA,
423 Payment::TYPE_BCA_VA,
424 Payment::TYPE_EPAY_BRI,
425 ];
426
427 if (!in_array($post['payment_method'], $validPaymentMethods)) {
428 return $this->errorResponse(
429 $this->translator->trans(
430 'error.wrong_format',
431 array(
432 '%s%' => $this->translator->trans('payment method'),
433 )
434 )
435 );
436 }
437
438 if (!isset($post['shipping_company']) || $post['shipping_company'] === '') {
439 return $this->errorResponse(
440 $this->translator->trans(
441 'error.required',
442 array(
443 '%s%' => $this->translator->trans('shipping_company'),
444 )
445 )
446 );
447 }
448
449 if ($post['payment_method'] == Payment::TYPE_MANDIRI_SMSBANK
450 || $post['payment_method'] == Payment::TYPE_KLIKBCA
451 || $post['payment_method'] == Payment::TYPE_KREDIVO
452 ) {
453 if (!isset($post['shoppingcart_meta'])) {
454 return $this->errorResponse(
455 $this->translator->trans(
456 'error.required',
457 array(
458 '%s%' => $this->translator->trans('shoppingcart_meta'),
459 )
460 )
461 );
462 }
463
464 $meta = $post['shoppingcart_meta'];
465
466 switch ($post['payment_method']) {
467 case Payment::TYPE_MANDIRI_SMSBANK :
468 if (!isset($meta['phone_no'])) {
469 return $this->errorResponse(
470 $this->translator->trans(
471 'error.required',
472 array(
473 '%s%' => $this->translator->trans('shoppingcart_meta: phone_no'),
474 )
475 )
476 );
477 }
478 break;
479 case Payment::TYPE_KLIKBCA:
480 if (!isset($meta['klikbca_id'])) {
481 return $this->errorResponse(
482 $this->translator->trans(
483 'error.required',
484 array(
485 '%s%' => $this->translator->trans('shoppingcart_meta: klikbca_id'),
486 )
487 )
488 );
489 }
490 break;
491 case Payment::TYPE_KREDIVO:
492 if (!isset($meta['kredivo_installment'])) {
493 return $this->errorResponse(
494 $this->translator->trans(
495 'error.required',
496 array(
497 '%s%' => $this->translator->trans('shoppingcart_meta: kredivo_installment'),
498 )
499 )
500 );
501 }
502 }
503 }
504
505 return true;
506 }
507
508 private function sendMailOrderCompleted(Transaction $transaction)
509 {
510 $promoRepo = $this->em->getRepository('ORORICoreBundle:Promo');
511 $transactionRepo = $this->em->getRepository('ORORICoreBundle:Transaction');
512 $data = $transactionRepo->getEmailData($transaction);
513
514 // Promo Free cushion
515 /*$promoDoubleWedding = $promoRepo->getPromoGoldPoint();
516 $start = \DateTime::createFromFormat('Y-m-d H:i:s', $promoDoubleWedding['rule']['double_wedding']['start']);
517 $end = \DateTime::createFromFormat('Y-m-d H:i:s', $promoDoubleWedding['rule']['double_wedding']['end']);
518
519 if ($this->timeInit <= $end) {
520 foreach ($data->products as $key => $row) {
521 if (in_array(strtolower($row['code']), $promoDoubleWedding['rule']['double_wedding']['conditions']['code']['in'])
522 || strtolower($row['category']) === 'ethnic') {
523 $data->products[$key]['info_html'] .= '<br /> <strong>Free Cushion</strong>';
524 }
525 }
526 }*/
527
528 $data->header1 = 'THANKS';
529 $data->header2 = 'FOR ORDERING';
530 $data->transaction_id = $transaction->getPaymentConfirmationCode();
531
532 $data->footer = $this->renderView('ORORIWorkerBundle:Partials:order-confirmation-footer.html.twig')
533 .$this->renderView('ORORIWorkerBundle:Partials:free-shipping-footer.html.twig');
534 $subject = 'Konfirmasi Order ORORI.com';
535 $subject2 = '[AUTO NOTIFICATION] Customer Order';
536 $body = $this->renderView('ORORIWorkerBundle:Mail:order-confirmation.html.twig', (array) $data);
537
538 $ororiMailNotification = $this->container->getParameter('mailnotification');
539
540 // Mail to sales
541 $this->sendMail($ororiMailNotification['sales'], $subject2, $body);
542
543 // Mail to customer
544 $this->sendMail($data->email, $subject, $body);
545
546 return true;
547 }
548
549 /**
550 * @param array $post
551 * @param $customer \ORORI\CoreBundle\Entity\Customer
552 * @param $username string
553 *
554 * @return JsonResponse
555 */
556 private function createOrder(array $post, $customer, $username)
557 {
558 $this->em->getConnection()->beginTransaction();
559
560 /* @var $transactionRepo \ORORI\CoreBundle\Repository\TransactionRepository */
561 $transactionRepo = $this->em->getRepository('ORORICoreBundle:Transaction');
562 /* @var $cartRepo \ORORI\CoreBundle\Repository\ShoppingCartRepository */
563 $cartRepo = $this->em->getRepository('ORORICoreBundle:ShoppingCart');
564 /* @var $prodRepo \ORORI\CoreBundle\Repository\ProductRepository */
565 $prodRepo = $this->em->getRepository('ORORICoreBundle:Product');
566
567 $isDiscHasFlashSale=$prodRepo->hasBuyFlashSale($customer->getId());
568
569 // Check customer shopping cart
570 $carts = $cartRepo->createQueryBuilder('sc')
571 ->join('sc.product', 'p')
572 ->where("sc.customer = '{$customer->getId()}'")
573 //->andWhere('sc.isActive = 1')
574 ->andWhere('sc.id IN (:ids)')
575 ->addOrderBy('p.calculatedPrice', 'ASC')
576 ->setParameter(':ids', explode(',', $post['shopping_cart']))
577 ->getQuery()
578 ->getResult()
579 ;
580 if (!$carts) {
581 return $this->errorResponse($this->translator->trans('error.required', array('%s%' => $this->translator->trans('product'))));
582 }
583
584 // Transaction parameter
585 $uniqueAdd = empty($post['unique_code']) ? 0 : $post['unique_code'];
586 $totalItem = 0;
587 $disc = 0;
588 $cashback = 0;
589 $surcharge = 0;
590 $tax = 0;
591 $basePrice = 0;
592 $finalPrice = 0;
593 $details = [];
594 $isMobile = isset($post['is_mobile']) ? $post['is_mobile'] : 0;
595 // Voucher parameter
596 $cartIds = [];
597
598 /* @var $cart \ORORI\CoreBundle\Entity\ShoppingCart */
599 $productDatas = [];
600 $transaction = new Transaction();
601 $multipleDiscount = $this->container->get('orori.promotion.multiple_discount_bank_promotion');
602 $multipleDiscount->setPaymentMethod($post['payment_method']);
603 $isMultipleDiscount = true;
604
605 $totalGroupBuy = 0;
606 $point = 0;
607 $isPromoWeddingRing = false;
608 $isGoldbarDoubleGP = false;
609 $isBoxDoubleGP = false;
610
611 $haveBoughtBefore = $transactionRepo->findOneBy([
612 'customer' => $customer,
613 ]);
614 $existing = $haveBoughtBefore instanceof Transaction;
615
616 $logger = $this->container->get('monolog.logger.payment_channel');
617
618 $isDiamondJewelryDoubleGP = false;
619 $diamondJewelryDouble = array(
620 'diamond_women_ring', 'diamond_pendant', 'diamond_earring', 'solitaire_ring', 'diamond_religious', 'diamond_men_ring',
621 'solitaire_earring', 'solitaire_pendant', 'diamond_bracelet', 'diamond_charm', 'alphabet_frame_yellow',
622 );
623
624 $isBraceletDoubleGP = false;
625 $blaceletDoubleGP = array('gold_bracelet', 'gold_ankle_bracelet', 'ubs_bangle');
626
627 $voucherManager = new VoucherManager();
628 $customerNode = new \ORORI\CoreBundle\Neo4j\Model\Customer($this->container);
629
630 // code by jacky : check promo buy 1 get 1 dan promo buy 1 free other product
631 $this->curBuy1Get1 = [];
632 $this->curBuy1DiscOther = [];
633 $promoRepo = $this->em->getRepository('ORORICoreBundle:Promo');
634 $promoBuy1Disc1 = $promoRepo->getPromoBuy1Disc1();
635 $promoBuy1DiscOther1 = $promoRepo->getPromoBuy1DiscOther1();
636
637 foreach ($carts as $cart) {
638 if ( is_array($promoBuy1Disc1) && !empty($promoBuy1Disc1) ) {
639 $this->curBuy1Get1 = $promoRepo->checkBuy1Disc1($prodRepo->getEntityData($cart->getProduct()), $this->curBuy1Get1, $promoBuy1Disc1);
640 }
641
642 if ( is_array($promoBuy1DiscOther1) && !empty($promoBuy1DiscOther1) ) {
643 $this->curBuy1DiscOther = $promoRepo->checkBuy1DiscOther1($prodRepo->getEntityData($cart->getProduct()), $this->curBuy1DiscOther, $promoBuy1DiscOther1);
644 }
645 }
646
647 $this->curBuy1Get1 = $promoRepo->manipulateBuy1Disc1($this->curBuy1Get1);
648
649 foreach ($carts as $cart) {
650 $curMeta = (array) $cart->getProduct()->getMeta();
651 // Graph data
652 $customerNode->insertRelationType($customer, $cart->getProduct(), \ORORI\CoreBundle\Neo4j\Relationship::BUY);
653
654 $goldVal = 0;
655 $nonGoldVal = 0;
656 // GPRED is GP redeem voucher and can be used for all items
657 if (!empty($post['voucher_code']) && strtoupper(substr($post['voucher_code'], 0, 5)) !== 'GPRED'
658 && ($prodRepo->isFlashSaleProduct($cart->getProduct()) || $prodRepo->isSpecialPromotion($cart->getProduct()))) {
659 if (!$voucherManager->isReferralVoucher($post['voucher_code'])) {
660 return $this->errorResponse('Voucher tidak bisa digunakan untuk product flash sale maupun promo khusus');
661 }
662 }
663
664// if ('gold' === $cart->getProduct()->getType() && 2 === (int) $post['payment_method']) {
665// return $this->errorResponse('This payment method is not allowed.');
666// }
667
668 //flash sale
669 if ($prodRepo->isFlashSaleProduct($cart->getProduct())) {
670 if ($cart->getProduct()->getQuantity() - $cart->getCount() < 0) {
671 return $this->errorResponse('Product flash sale telah habis.');
672 }
673
674 $filterTransaction = array(
675 'customer' => $customer,
676 'with_detail' => true,
677 'product_code' => $prodRepo->getFlashSaleProduct(),
678 'start_date' => '2016-01-17 10:00:00',
679 'end_date' => '2016-01-30 23:59:59',
680 );
681 $flashSaleTransaction = $transactionRepo->fetchAll($filterTransaction);
682 if (count($flashSaleTransaction) > 0) {
683 return $this->errorResponse('Maaf. Anda sudah pernah membeli produk flash sale sebelumnya.');
684 }
685
686 if ($post['payment_method'] == 2) {
687 $metaShoppingCart = $cart->getMeta();
688 if (array_key_exists('cc_surcharge', $metaShoppingCart)) {
689 return $this->errorResponse('Metode pembayaran ini tidak diizinkan.');
690 }
691 } elseif ($post['payment_method'] == 3) {
692 return $this->errorResponse('Metode pembayaran ini tidak diizinkan.');
693 }
694 }
695
696 $flashController = $this->container->get('orori.promotion.controller.flash_discount');
697 $flashController->setContainer($this->container);
698 $flashSale = $flashController->isFlashSalable($customer, $cart->getProduct());
699 if (!$flashSale['status']) {
700 return $this->errorResponse($flashSale['message']);
701 }
702
703 // code by jacky : check promo buy 1 get 1 dan promo buy 1 free other product
704 if (is_array($this->curBuy1Get1) && !empty($this->curBuy1Get1)) {
705 $this->curBuy1Get1['is_disc_item'] = false;
706 $this->curBuy1Get1['disc_1'] = 0;
707 $this->curBuy1Get1['disc_2'] = 0;
708 $this->curBuy1Get1 = $promoRepo->countDiscOfBuy1Disc1($prodRepo->getEntityData($cart->getProduct()), $this->curBuy1Get1, $promoBuy1Disc1);
709 }
710
711 if (is_array($this->curBuy1DiscOther) && !empty($this->curBuy1DiscOther)) {
712 $this->curBuy1DiscOther['is_disc_item'] = false;
713 $this->curBuy1DiscOther['disc_1'] = 0;
714 $this->curBuy1DiscOther['disc_2'] = 0;
715 $this->curBuy1DiscOther = $promoRepo->countDiscOfBuy1DiscOther1($prodRepo->getEntityData($cart->getProduct()), $this->curBuy1DiscOther, $promoBuy1DiscOther1);
716 }
717
718 $productData = $prodRepo->getFrontendEntityData(
719 $cart->getProduct(),
720 (array) $cart->getMeta(),
721 $isMobile,
722 $isDiscHasFlashSale,
723 $this->curBuy1Get1,
724 $this->curBuy1DiscOther
725 );
726
727 $voucherManager->addProduct($cart->getProduct(), $productData, $cart->getCount());
728
729 $productDatas[] = $productData;
730
731 $prod = $cart->getProduct();
732 $qty = $cart->getCount();
733
734 // Double Gold Point
735 // Wedding Ring Promo
736 if (!$isPromoWeddingRing && Product::TYPE_RING === $prod->getType()) {
737 $isPromoWeddingRing = true;
738 }
739 // Goldbar
740 else if (!$isGoldbarDoubleGP && Product::TYPE_GOLD === $prod->getType()) {
741 $isGoldbarDoubleGP = true;
742 }
743 // Goldbar
744 else if (!$isBoxDoubleGP && (Product::TYPE_BOX === $prod->getType() || Product::TYPE_CLEANING === $prod->getType()) && $productData['calculated_price'] >= 100000) {
745 $isBoxDoubleGP = true;
746 } else if (in_array(strtolower($prod->getCategory()), $diamondJewelryDouble)) {
747 $isDiamondJewelryDoubleGP = true;
748 } else if (in_array($prod->getCategory(), $blaceletDoubleGP)) {
749 $isBraceletDoubleGP = true;
750 }
751
752 $currentBase = $productData['base_price'] * $cart->getCount();
753 $currentDisc = $productData['discount_value'] * $cart->getCount();
754 $currentTax = $productData['tax'] * $cart->getCount();
755 $currentGroupBuyDisc = $productData['groupbuy_discount_value'] * $cart->getCount();
756 $currentFinal = $productData['final_price'] * $cart->getCount();
757
758 //$currentFinal=$currentFinal-$currentGroupBuyDisc;
759
760 $basePrice += $currentBase;
761 $tax += $currentTax;
762
763 //for multiple discount
764 $multipleDiscountType = array('diamondjewelry', 'engagement', 'mensring');
765 if (
766 !in_array($cart->getProduct()->getType(), $multipleDiscountType) ||
767 $prodRepo->isSpecialPromotion($cart->getProduct())
768 ) {
769 $isMultipleDiscount = false;
770 }
771
772 $disc += $currentDisc;
773 $finalPrice += $currentFinal;
774
775 // Add detail
776 $detail = new TransactionDetail();
777 $detail->setProduct($cart->getProduct())
778 ->setProductData($productData)
779 ->setCount($cart->getCount())
780 ->setSubtotal($currentBase)
781 ->setDiscount($currentDisc)
782 ->setTax($currentTax)
783 ->setGroupbuyDiscount($currentGroupBuyDisc)
784 ->setTotalPrice($currentFinal)
785 ->setCreatedBy($post['creator']);
786
787 $totalGroupBuy += $currentGroupBuyDisc;
788
789 $cart->setRemark('Bought')
790 ->setPageCookie('')
791 ->setIsActive(false);
792 $details[] = $detail;
793 $totalItem += $cart->getCount();
794
795 // Cut stock only for goldjewelry product, cleaning, box, diamondjewelry, UBS
796 if ((
797 in_array($prod->getType(), $prodRepo->getCuttingStockType()) || $prodRepo->isFlashSaleProduct($prod)
798 || $prod->getIsCuttingStock()
799 ) && $prod->getQuantity() != 0
800 && $prod->getCategory() !== Product::CATEGORY_GOLD_PENDANT_ALPHABET) {
801 if ($prod->getQuantity() < $qty) {
802 $qty = $prod->getQuantity();
803 }
804
805 $prod->addQuantity(-1 * $qty);
806
807 // Delete other customers shopping cart if this product stock = 0
808 if ((int) $prod->getQuantity() === 0) {
809 $sql = 'UPDATE shopping_cart SET is_active = 0 WHERE product_id IN ('.$prod->getId().')';
810 $stmt = $this->em->getConnection()->prepare($sql);
811 $stmt->execute();
812 }
813 }
814 // For custom product, remove from website immediately so it cannot be bought by others
815 if (
816 $prod->getType() === Product::TYPE_CUSTOM &&
817 strtolower($prod->getCode()) !== 'repair' &&
818 strtolower($prod->getCode()) !== 'free-antam-1gr' &&
819 strtolower($prod->getCode()) !== 'free-antam-1gr-red' &&
820 !in_array($prod->getCode(), $prodRepo->getVoucherFlashSale()) &&
821 strtoupper($prod->getCode()) !== 'VC-FLASH-650-IP'
822 ) {
823 $prod->setShowWebsite(false);
824 }
825
826 // Voucher
827 $cartIds[] = $cart->getId();
828
829 // GoldPoint
830 if (in_array($productData['type'], Product::$listGoldPoint)) {
831 $goldVal = $currentFinal;
832 } else {
833 $nonGoldVal = $currentFinal;
834 }
835
836 // Gold Point
837 $goldPoint = 0;
838 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) {
839 $goldPoint = (floor($nonGoldVal / Transaction::GOLD_POINT_PARITY_NONGOLD) * $customer->getLevel()) + (floor($goldVal / Transaction::GOLD_POINT_PARITY_GOLD) * $customer->getLevel());
840
841 if (date('Y-m-d') >= '2016-09-20' && date('Y-m-d') <= '2016-09-30' && $isPromoWeddingRing) {
842 $goldPoint = ((floor($nonGoldVal / Transaction::GOLD_POINT_PARITY_NONGOLD) * $customer->getLevel())) + (floor($goldVal / Transaction::GOLD_POINT_PARITY_GOLD) * $customer->getLevel()) * 2;
843
844 $isPromoWeddingRing = false;
845 }
846
847 if (date('Y-m-d') >= '2016-08-17' && date('Y-m-d') <= '2016-09-30' && $isGoldbarDoubleGP) {
848 $goldPoint = ((floor($nonGoldVal / Transaction::GOLD_POINT_PARITY_NONGOLD) * $customer->getLevel()) + (floor($goldVal / Transaction::GOLD_POINT_PARITY_GOLD) * $customer->getLevel())) * 2;
849
850 $isGoldbarDoubleGP = false;
851 }
852
853 if (date('Y-m-d') >= '2016-08-30' && date('Y-m-d') <= '2016-09-30' && $isBoxDoubleGP) {
854 $goldPoint = ((floor($nonGoldVal / Transaction::GOLD_POINT_PARITY_ACCESSORIES) * $customer->getLevel()) + (floor($goldVal / Transaction::GOLD_POINT_PARITY_ACCESSORIES) * $customer->getLevel())) * 2;
855
856 $isBoxDoubleGP = false;
857 }
858
859 if (date('Y-m-d') >= '2016-09-30' && date('Y-m-d') <= '2016-10-16' && $isBraceletDoubleGP) {
860 $goldPoint = ((floor($nonGoldVal / Transaction::GOLD_POINT_PARITY_NONGOLD) * $customer->getLevel()) + (floor($goldVal / Transaction::GOLD_POINT_PARITY_NONGOLD) * $customer->getLevel())) * 2;
861
862 $isBraceletDoubleGP = false;
863 }
864
865 if (date('Y-m-d') >= '2016-09-28' && date('Y-m-d') <= '2016-10-16' && $isDiamondJewelryDoubleGP) {
866 $goldPoint = ((floor($nonGoldVal / Transaction::GOLD_POINT_PARITY_NONGOLD) * $customer->getLevel()) + (floor($goldVal / Transaction::GOLD_POINT_PARITY_NONGOLD) * $customer->getLevel())) * 3;
867
868 $isDiamondJewelryDoubleGP = false;
869 }
870 }
871
872 // code by jacky : check promo multiple goldpoint
873 $multiplePoint = $promoRepo->getPromoValue($prodRepo->getEntityData($cart->getProduct()), 1, $promoRepo->getPromoGoldPoint());
874 $goldPoint = $multiplePoint*$goldPoint;
875 $point += $goldPoint;
876
877 $this->em->persist($cart);
878 $this->em->persist($prod);
879
880 // Save to table_modify before flush to make this work
881 $this->logModified($prod, 'ORDER on '.$this->timeInit->format('Y-m-d H:i:s'));
882 }
883
884 $country = !empty($post['country']) && Country::isExist($post['country']) ? $post['country'] : Country::INDONESIA;
885
886 $metadata = array();
887 if (array_key_exists('shoppingcart_meta', $post)) {
888 $metadata = (array) $post['shoppingcart_meta'];
889 }
890
891 $post['is_multiple_discount'] = $isMultipleDiscount;
892 $multipleDiscount->calculate($finalPrice, 0, array_merge($metadata, $post, array('is_multiple_discount' => $isMultipleDiscount)));
893 $finalPrice = $finalPrice - $multipleDiscount->getValue();
894 $post['sinarmas_discount'] = $multipleDiscount->getValue();
895 $disc = $disc + $multipleDiscount->getValue();
896
897 // Add discount voucher
898 if (!empty($post['voucher_code'])) {
899 $voucher = $voucherManager->isAllowedVoucher($post['voucher_code'], $cartIds, null, $isMobile, $customer);
900 if (!$voucher instanceof Voucher) {
901// $customerReferral = $this->get('doctrine.orm.entity_manager')->getRepository('ORORICoreBundle:Customer')->findOneBy(array('uniqueCode' => $post['voucher_code']));
902 if ($voucherManager->isReferralVoucher($post['voucher_code'])) {
903 $transaction->setVoucherCode($post['voucher_code']);
904
905 $transaction->setVoucherDiscount($voucherManager->getDiscount());
906 $finalPrice -= $voucherManager->getDiscount();
907// $point -= $voucherManager->getTotalPoint();
908 } else {
909 return $this->errorResponse($voucher);
910 }
911 } else {
912 if (!empty($voucher->getServiceId())) {
913 $promotionBaseOnVoucherHandler = $this->get('orori.voucher.promotion_factory');
914 $promotionBaseOnVoucherHandler->setTransaction($transaction);
915 $promotionBaseOnVoucherHandler->compile($voucher->getCode());
916 } else {
917 $voucherDisc = $voucher->getValue();
918 // Return discount value to percentage because some voucher can be used multiple times
919 if ($voucher->getVoucherType() === Voucher::VOUCHERTYPE_DISCOUNT) {
920 $sql = "SELECT * FROM voucher WHERE id = '{$voucher->getId()}'";
921 $stmt = $this->em->getConnection()->prepare($sql);
922 $stmt->execute();
923 $realVoucher = $stmt->fetchAll();
924 $voucher->setValue($realVoucher[0]['value']);
925 }
926
927 $timeOfUsed = $voucher->getTimeOfUsed() ?: 0;
928 $voucher->setTransaction($transaction)
929 ->setTimeOfUsed($timeOfUsed + 1);
930 $transaction->setVoucherDiscount($voucherDisc)
931 ->setVoucherCode($voucher->getCode());
932
933 $finalPrice -= $voucherDisc;
934 if ($finalPrice < 0) {
935 $finalPrice = 0;
936 $tax = 0;
937 }
938
939 // Save voucher transaction
940 $this->em->persist($voucher);
941 }
942 }
943 } elseif (0 < $multipleDiscount->getValue()) {
944 $transaction->setVoucherDiscount($multipleDiscount->getValue());
945 $transaction->setVoucherCode('BANK_PROMO');
946 }
947
948 if (array_key_exists('real_shipping_fee', $post)) {
949 $transaction->setRealShippingFee($post['real_shipping_fee']);
950 }
951
952 // For transfer add unique code
953 if ((int) $post['payment_method'] === Payment::TYPE_TRANSFER) {
954 $basePrice += $uniqueAdd;
955 $finalPrice += $uniqueAdd;
956 }
957
958 //Buy With Goldpoint Here
959 if (!empty($post['goldpoint']) && $post['goldpoint'] >= 10 && $customer->getPoint() >= 10) {
960 $voucher = $this->generateGoldPointVoucher($post['goldpoint'], $customer);
961 $transaction->setVoucherDiscount($voucher->getValue())
962 ->setVoucherCode($voucher->getCode());
963 $customer->setPoint($customer->getPoint() - $post['goldpoint']);
964
965 $finalPrice -= $voucher->getValue();
966 if ($finalPrice < 0) {
967 $finalPrice = 0;
968 $tax = 0;
969 }
970 }
971
972 $transaction->setBillingData($post['billing_data'])
973 ->setCustomerData($post['customer_data'])
974 ->setDeliveryData($post['delivery_data'])
975 ->setCountry($country)
976 ->setCustomer($customer)
977 ->setDiscount($disc)
978 ->setStatus($transactionStatus)
979 ->setSubtotal($basePrice)
980 ->setSurchargeFee($surcharge)
981 ->setPaymentType($post['payment_method'])
982 ->setTax($tax)
983 ->setCashback($cashback)
984 ->setGroupBuyDiscount($totalGroupBuy)
985 ->setTotalPrice($finalPrice)
986 ->setTotalItem($totalItem)
987 ->setPoint($point)
988 ->setCreatedAt($this->timeInit)
989 ->setCreatedBy($post['creator'])
990 ;
991
992 if (isset($post['shipping_company']) && $post['shipping_company'] !== '') {
993 $transaction->setShippingCompany($post['shipping_company']);
994 }
995 if (!empty($post['shipping_fee'])) {
996 $transaction->setShippingFee($post['shipping_fee']);
997 }
998 if (!empty($post['surcharge_fee'])) {
999 $transaction->setSurchargeFee($post['surcharge_fee']);
1000 }
1001
1002 // Prepare transaction meta
1003 // Used for storing extra attribute for payment
1004 // eg. for klikbca, store klikbca user id
1005 // for mandiri sms, store phone no
1006 // for bca klikpay, store tenor for each item bought
1007
1008 $logger->addInfo(sprintf('Post Data: %s', json_encode($post)));
1009
1010 if (isset($post['shoppingcart_meta']) && !empty($post['shoppingcart_meta'])) {
1011 $transaction->setPaymentMeta($post['payment_method'], $post['shoppingcart_meta']);
1012 }
1013 if (!empty($post['ga_utm'])) {
1014 $transaction->setGaUtm($post['ga_utm']);
1015 }
1016
1017 // Create transaction
1018 $this->em->persist($transaction);
1019 $this->em->flush();
1020
1021 /*
1022 * Tambahan kode by Rijal
1023 * Redeem voucher sodexo
1024 */
1025 if (!empty($post['voucher_code']) and strtolower(substr($post['voucher_code'], 0, 2)) == 'sx') {
1026 // simpan voucher sodexo
1027 $sodexo = new Sodexo();
1028 $redeemSodexo = $sodexo->redeemVouchers(array($post['voucher_code']), $transaction->getId(), count($details).'/'.$transaction->getId().date('/Ymd').rand(111111, 999999));
1029 if (!$redeemSodexo['success']) {
1030 return $this->errorResponse('Error saat redeem voucher sodexo : '.$redeemSodexo['message']);
1031 }
1032 }
1033
1034// 1/16706/20141208163231
1035// number of product bought / invoice id / YYYYMMDD 6 digit random number
1036 $invoiceNo = count($details).'/'.$transaction->getId().date('/Ymd').rand(111111, 999999);
1037 $transaction->setTransactionNo($invoiceNo);
1038
1039 // Update transaction id
1040 foreach ($details as $transactionDetail) {
1041 $product = $transactionDetail->getProduct();
1042 $product->setBuyCount($product->getBuyCount()+$transactionDetail->getCount());
1043 $this->em->persist($product);
1044
1045 $transactionDetail->setTransaction($transaction);
1046 $this->em->persist($transactionDetail);
1047
1048 $transaction->setTransactionDetail($transactionDetail);
1049
1050 // saving oro-box
1051 if (isset($post['simpan']) && !empty($post['simpan']) && $post['simpan']) {
1052 $startDate = $this->timeInit;
1053 $endDate = $startDate->add(new DateInterval("P{$post['period']}M"));
1054
1055 $goldDeposit = new \ORORI\GoldDepositBundle\Entity\GoldDeposit();
1056 $goldDeposit->setTransaction($transaction);
1057 $goldDeposit->setProduct($product);
1058 $goldDeposit->setQty($transactionDetail->getCount());
1059 $goldDeposit->setCustomer($customer);
1060 $goldDeposit->setPeriod($post['period']);
1061 $goldDeposit->setStartDate($startDate);
1062 $goldDeposit->setEndDate($endDate);
1063 $goldDeposit->setEndStatus(null);
1064 $goldDeposit->setFee(0);
1065 $goldDeposit->setIsActive(false);
1066 $goldDeposit->setCreatedAt($startDate);
1067 $goldDeposit->setCreatedBy($customer->getUsername());
1068 $goldDeposit->setUpdatedAt($startDate);
1069 $goldDeposit->setUpdatedBy($customer->getUsername());
1070 }
1071 }
1072
1073 // Pay with GP add customer point log
1074 if (!empty($post['goldpoint']) && $post['goldpoint'] >= 10 && $customer->getPoint() >= 10) {
1075 $custPoint = new CustomerPoint();
1076 $custPoint->setCustomer($customer)
1077 ->setContainer('transaction')
1078 ->setContainerId($transaction->getId())
1079 ->setPoint('-'.$post['goldpoint'])
1080 ->setDescription('Pay with GP')
1081 ->setValidUntil($this->timeInit)
1082 ->setIsActive(1)
1083 ->setCreatedBy($customer->getUsername())
1084 ->setCreatedAt($this->timeInit);
1085 $this->em->persist($custPoint)
1086 ;
1087 }
1088
1089 $this->em->persist($transaction);
1090 // Create transaction detail
1091 $this->em->flush();
1092
1093 // Send email to corresponding customer
1094 $this->sendMailOrderCompleted($transaction);
1095
1096 $data = $transactionRepo->getEntityData($transaction);
1097
1098 // Update transaction detail
1099 $transactionDetailRepo = $this->em->getRepository('ORORICoreBundle:TransactionDetail');
1100 $detailData = [];
1101 foreach ($details as $transactionDetail) {
1102 $detailData[] = $transactionDetailRepo->getFrontendEntityData($transactionDetail);
1103 }
1104
1105 $this->em->getConnection()->commit();
1106
1107 if ('prod' === $this->container->get('kernel')->getEnvironment()) {
1108 $cicilan = array();
1109 if (isset($post['shoppingcart_meta']) && is_array($post['shoppingcart_meta']) && array_key_exists('cc_installment', $post['shoppingcart_meta'])) {
1110 $cicilan = explode('-', $post['shoppingcart_meta']['cc_installment']);
1111 }
1112
1113 if (isset($post['payment_method']) && 2 === (int) $post['payment_method'] && 2 === count($cicilan)) {
1114 $content = 'Order No '.$transaction->getTransactionNo().' request cicilan '.$cicilan[1].' bulan via credit card '.$cicilan[0];
1115 $this->sendMail(array('finance@orori.com', 'sales.team@orori.com'), 'REPORT CICILAN '.$transaction->getId(), $content, null, null);
1116 }
1117
1118 // Add to mailchimp list
1119 $gender = strtolower($customer->getGender()) === 'm' ? 'male' : 'female';
1120 try {
1121 $this->get('gearman')->doBackgroundJob(
1122 JobName::MAILCHIMP_CHECKOUT, json_encode([
1123 'customer_id' => $customer->getId(),
1124 'email' => $customer->getEmail(),
1125 'fullname' => $customer->getFirstname().' '.$customer->getLastname(),
1126 'gender' => $gender,
1127 'date' => $customer->getJoinDate()->format('d-m-Y'),
1128 'amount' => $transaction->getTotalPrice(),
1129 ]));
1130 } catch (JobDoesNotExistException $e) {
1131 $this->log($e);
1132 } catch (WorkerDoesNotExistException $e) {
1133 $this->log($e);
1134 }
1135 }
1136
1137 return $this->successResponse(
1138 [
1139 'transaction' => $data,
1140 'detail' => $detailData,
1141 'payment' => $this->createPayment($transaction, $post['payment_method'], $username),
1142 'existing_customer' => $existing,
1143 // Create payment or redirect
1144 ],
1145 HttpStatus::HTTP_CREATED
1146 );
1147 }
1148
1149 private function createPayment(Transaction $transaction, $paymentMethod, $username)
1150 {
1151 $paymentLogger = $this->container->get('monolog.logger.payment_channel');
1152 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Start payment, method: '.$paymentMethod);
1153 // Re-populate transaction
1154 /* @var $transactionRepo \ORORI\CoreBundle\Repository\TransactionRepository */
1155 $transactionRepo = $this->em->getRepository('ORORICoreBundle:Transaction');
1156 $savedTransaction = $transactionRepo->find($transaction->getId());
1157
1158 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Get Saved transaction ');
1159
1160 $paymentOptionFactory = new PaymentOptionFactory();
1161 $options = $paymentOptionFactory
1162 ->setContainer($this->container)
1163 ->setPaymentMethod($paymentMethod)
1164 ->setTransaction($savedTransaction)
1165 ->setActionType(PaymentOptionFactory::ACTION_TYPE_PAYMENT)
1166 ->compile()
1167 ;
1168
1169 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Payment Options : '.json_encode($options));
1170
1171 $paymentFactory = new PaymentHandlerFactory();
1172 $handler = $paymentFactory
1173 ->setContainer($this->container)
1174 ->setPaymentMethod($paymentMethod)
1175 ->compile()
1176 ;
1177
1178 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Payment Handler : '.json_encode($handler));
1179 $handler->setOptions($options);
1180
1181 if ($handler instanceof BaseRedirectPaymentHandler) {
1182 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Processing Payment Redirection ');
1183
1184 $output = [
1185 'type' => PaymentHandlerFactory::PAYMENT_PAGE_REDIRECTION,
1186 'redirect' => $handler->getRedirectionPage(),
1187 'payload' => $handler->getRedirectionPayload(),
1188 'status' => Payment::STATUS_PENDING,
1189 ];
1190 } else if ($handler instanceof EPayBri) {
1191 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Processing Payment Epay BRI ');
1192
1193 $handler->sendPaymentRequest();
1194
1195 $output = [
1196 'type' => PaymentHandlerFactory::PAYMENT_PAGE_REDIRECTION,
1197 'request' => $handler->getRequestPayload(),
1198 'response' => $handler->getResponsePayload(),
1199 'redirect' => $handler->getRedirectionPage(),
1200 'payload' => array(),
1201 'status' => $handler->getPaymentStatus(),
1202 ];
1203 } elseif ($handler instanceof BaseDirectPaymentHandler) {
1204 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Processing Payment Direct ');
1205
1206 $handler->sendPaymentRequest();
1207
1208 /* @var Transaction $savedTransaction */
1209 $metadata = $savedTransaction->getMeta();
1210 $handlerResponse = $handler->getResponsePayload();
1211 if ($paymentMethod == Payment::TYPE_BNI_ECOLLECTION && Payment::STATUS_SUCCESS) {
1212 $metadata->virtual_account = $handlerResponse['virtual_account'];
1213 $savedTransaction->setMeta(json_encode($metadata));
1214
1215 $entityManager = $this->getDoctrine()->getManager();
1216 $entityManager->persist($savedTransaction);
1217 $entityManager->flush();
1218 }
1219
1220 $output = [
1221 'type' => PaymentHandlerFactory::PAYMENT_PAGE_DIRECT,
1222 'payload' => $handler->getRequestPayload(),
1223 'response' => $handlerResponse,
1224 'status' => $handler->getPaymentStatus(),
1225 ];
1226 } elseif ($handler instanceof BaseTwoStepPaymentHandler) {
1227 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Processing Two Phase Payment');
1228 $handler->sendPaymentRequest();
1229//kredivo checking
1230 $output = [
1231 'type' => PaymentHandlerFactory::PAYMENT_PAGE_TWO_PHASE,
1232 'request' => $handler->getRequestPayload(),
1233 'response' => $handler->getResponsePayload(),
1234 'redirect' => $handler->getRedirectionPage(),
1235 'payload' => $handler->getRedirectionPayload(),
1236 'status' => $handler->getPaymentStatus(),
1237 ];
1238 } else if ($handler instanceof EPayBri) {
1239 $output = [
1240 'type' => PaymentHandlerFactory::PAYMENT_PAGE_TWO_PHASE,
1241 'request' => $handler->getRequestPayload(),
1242 'response' => $handler->getResponsePayload(),
1243 'redirect' => $handler->getResponsePayload()->redirect_url,
1244 'payload' => array(),
1245 'status' => $handler->getPaymentStatus(),
1246 ];
1247 } else { // $handler is instanceof PaymentManualInterface
1248 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Processing Payment Manual ');
1249
1250 $output = [
1251 'type' => PaymentHandlerFactory::PAYMENT_MANUAL,
1252 ];
1253 }
1254
1255 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Payment Output : '.json_encode($output));
1256
1257 $paymentData = $this->logPaymentRequest($transaction, $paymentMethod, $output, $username);
1258 $output['data'] = $paymentData;
1259
1260 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Payment Data : '.json_encode($paymentData));
1261
1262 $paymentRepository = $this->em->getRepository('ORORICoreBundle:Payment');
1263 $payment = $paymentRepository->find($paymentData['id']);
1264
1265 // Post processing
1266 // We need to append metadata required for callback processing
1267 // ie. Thirdparty host hit our host, then process based on these appendedMeta
1268 if ($handler instanceof BaseTwoStepPaymentHandler) {
1269 $chargeMeta = $handler->getAppendMetadata();
1270 $paymentMeta = json_decode(json_encode($payment->getMeta()), true);
1271 $meta = array_merge($chargeMeta, $paymentMeta);
1272 $payment->setMeta($meta);
1273 $this->em->persist($payment);
1274 $this->em->flush();
1275
1276 $paymentLogger->info('[PAYMENT] '.$transaction->getTransactionNo().' Append metadata '.json_encode($meta));
1277 }
1278
1279 $virtualAccount = '';
1280 if (
1281 Payment::TYPE_PERMATA_VA === (int) $paymentMethod ||
1282 Payment::TYPE_MANDIRI_VA === (int) $paymentMethod ||
1283 Payment::TYPE_BCA_VA === (int) $paymentMethod ||
1284 Payment::TYPE_BNI_ECOLLECTION === (int) $paymentMethod
1285 ) {
1286 $customer=$transaction->getCustomer();
1287 if (Payment::TYPE_PERMATA_VA === (int) $paymentMethod){
1288 $tpl = 'ORORIApiBundle:Email:permata-va.html.twig';
1289 }
1290 elseif(Payment::TYPE_MANDIRI_VA === (int) $paymentMethod){
1291 $tpl = 'ORORIApiBundle:Email:mandiri-va.html.twig';
1292 }
1293 elseif(Payment::TYPE_BCA_VA === (int) $paymentMethod){
1294 $tpl = 'ORORIApiBundle:Email:bca-va.html.twig';
1295 }
1296 elseif(Payment::TYPE_BNI_ECOLLECTION === (int) $paymentMethod){
1297 $tpl = 'ORORIApiBundle:Email:bni-va.html.twig';
1298 $virtualAccount = $output['response']['virtual_account'];
1299 }
1300
1301 $details=[];
1302 $transactionRepo = $this->em->getRepository('ORORICoreBundle:Transaction');
1303 $data = (array) $transactionRepo->getEmailData($transaction);
1304// $transactionDetails=$transaction->getTransactionDetail();
1305// $prodRepo = $this->em->getRepository('ORORICoreBundle:Product');
1306// foreach ($transactionDetails as $i=>$detail){
1307// $product=$detail->getProduct();
1308// $file = substr($product->getMainImage(), 0, -4).'_s';
1309// $ext = substr($product->getMainImage(), -4);
1310// $frontEndData=$prodRepo->getFrontendEntityData($product);
1311// $details[$i]=[
1312// 'product_code' => $product->getCode(),
1313// 'product_name' => $product->getName(),
1314// 'product_calculated_price' => $frontEndData['calculated_price'],
1315// 'product_final_price' => $frontEndData['final_price'],
1316// 'product_description' => $product->getDescription(),
1317// 'product_main_image' =>$file.$ext,
1318// 'product_meta' => $product->getMeta(),
1319// ];
1320// }
1321//
1322 $data = array_merge([
1323 'fullname' => $customer->getFirstname() .' '. $customer->getLastname(),
1324 'transaction_no' => $transaction->getTransactionNo(),
1325 'transaction_date' => date('j F Y', $transaction->getCreatedAt()->getTimestamp()),
1326 'va_no' => $output['response']['trx_id'],
1327 'virtual_account' => $virtualAccount,
1328 'details' => $details,
1329 ], $data);
1330 $content = $this->renderView($tpl, (array) $data);
1331
1332 $this->sendMail(array($customer->getEmail()), 'Konfirmasi Order '.$transaction->getTransactionNo(), $content, null, null);
1333 }
1334
1335 return $output;
1336 }
1337
1338 /**
1339 * At this point, the log barely created.
1340 * Later on will be updated especially for redirection-type payment.
1341 *
1342 * @param Transaction $transaction
1343 * @param $paymentMethod
1344 * @param $output
1345 *
1346 * @return \ORORI\CoreBundle\Entity\Payment
1347 */
1348 private function logPaymentRequest(Transaction $transaction, $paymentMethod, $output, $username)
1349 {
1350 $paymentLogger = $this->container->get('monolog.logger.payment_channel');
1351 $paymentLogger->info('[PAYMENT] Insert payment data');
1352
1353 $payment = new Payment();
1354
1355 // prep data
1356 if (isset($output['payload']) && is_array($output['payload'])) {
1357 $output['payload'] = json_encode($output['payload']);
1358 }
1359
1360 if (isset($output['response']) && is_array($output['response'])) {
1361 $output['response'] = json_encode($output['response']);
1362 }
1363
1364 $meta = (array) $transaction->getMeta();
1365
1366 // Direct payment
1367 if (
1368 $paymentMethod == Payment::TYPE_BCA_KLIKPAY
1369 || $paymentMethod == Payment::TYPE_KLIKBCA
1370 || $paymentMethod == Payment::TYPE_MANDIRI_CLICKPAY
1371 || $paymentMethod == Payment::TYPE_MANDIRI_SMSBANK
1372 || $paymentMethod == Payment::TYPE_KREDIVO
1373 ) {
1374 $payment
1375 ->setStatus($output['status'])
1376 ->setRequestPayload($output['payload'])
1377 ->setResponsePayload($output['response'])
1378 ->setMeta($meta)
1379 ;
1380 }
1381 // Redirection payment
1382 elseif (
1383 $paymentMethod == Payment::TYPE_BCA_3_MONTH
1384 || $paymentMethod == Payment::TYPE_CIMB_CLICK
1385 || $paymentMethod == Payment::TYPE_VISAMASTER
1386 || $paymentMethod == Payment::TYPE_BNI_ECOLLECTION
1387 || $paymentMethod == Payment::TYPE_PERMATA_VA
1388 || $paymentMethod == Payment::TYPE_MANDIRI_VA
1389 || $paymentMethod == Payment::TYPE_BCA_VA
1390 || $paymentMethod == Payment::TYPE_EPAY_BRI
1391 ) {
1392 $payment
1393 ->setStatus(Payment::STATUS_PENDING)
1394 ->setRequestPayload($output['payload'])
1395 ->setMeta($meta)
1396 ;
1397 }
1398 // Manual payment
1399 else {
1400 $payment->setStatus(Payment::STATUS_PENDING);
1401 }
1402
1403 $payment
1404 ->setTransaction($transaction)
1405 ->setRefNo($transaction->getTransactionNo())
1406 ->setType($paymentMethod)
1407 ->setCreatedBy($username)
1408 ->setValue($transaction->getTotalPrice() + $transaction->getShippingFee() + $transaction->getSurchargeFee())
1409 ;
1410
1411 $this->em->persist($payment);
1412 $this->em->flush();
1413
1414 $paymentRepository = $this->em->getRepository('ORORICoreBundle:Payment');
1415
1416 return $paymentRepository->getEntityData($payment);
1417 }
1418
1419 private function generateGoldPointVoucher($point, Customer $customer)
1420 {
1421 $category = 'GOLDPOINT';
1422 $value = $point * 2000;
1423
1424 $voucher = new Voucher();
1425
1426 $voucher->setCode(sprintf('GP%s%s', $value, strtoupper(substr(md5(uniqid(rand(), true)), 0, 6))))
1427 ->setVoucherType(Voucher::VOUCHERTYPE_VALUE)
1428 ->setValue($value)
1429 ->setCreatedBy('SYSTEM')
1430 ->setDescription('GOLDPOINT VOUCHER FOR CUSTOMER WITH ID: '.$customer->getId())
1431 ->setMinimumPrice(0)
1432 ->setType($category)
1433 ->setCategory($category)
1434 ->setLimitOfUsed(1)
1435 ->setValidUntil(new \DateTime());
1436
1437 $entityManager = $this->getDoctrine()->getManager();
1438 $entityManager->persist($voucher);
1439 $entityManager->flush();
1440
1441 return $voucher;
1442 }
1443}