<?php
namespace App\Controller\Api;
use App\Entity\Booking;
use App\Entity\Cart;
use App\Entity\Custom;
use App\Entity\CustomCart;
use App\Entity\User;
use App\Form\BookingType;
use App\Form\CartType;
use App\Helpers\FormHelper;
use App\Helpers\ResponseCode;
use App\Helpers\TngGuestClient;
use App\Helpers\TngStaffClient;
use App\Repository\BookingRepository;
use App\Repository\CartRepository;
use App\Repository\CustomRepository;
use App\Repository\ServiceRepository;
use App\Repository\SubServiceRepository;
use App\Utils\Fondy;
use App\Utils\Mercure;
use App\Utils\Paginator;
use App\Utils\ResponseTrait;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
class CartContoller extends AbstractController
{
use ResponseTrait;
/**
* @Route(path="/api/cart", methods={"GET"})
*/
public function getCart(CartRepository $repository)
{
/** @var User $user */
$user = $this->getUser();
$cart = $repository->getByUser($user);
return $this->statusOk(
null,
null,
[
'items' => $cart,
]
);
}
/**
* @Route(path="/api/customs/archived", methods={"GET"})
*/
public function getCustomsArchived(Request $request, Paginator $paginatorService, PaginatorInterface $paginator, CustomRepository $customRepository)
{
$query = $customRepository->getByUser($this->getUser());
$items = $paginator->paginate(
$query,
$request->query->getInt('page', 1),
$request->query->getInt('limit', 10)
);
$items = $paginatorService->getResponsePaginate($items);
return $this->statusOk(
null,
null,
$items
);
}
/**
* @Route(path="/api/customs/archived/{id}", methods={"GET"})
*/
public function getCustomArchived(CartRepository $repository, CustomRepository $customRepository, $id)
{
/** @var User $user */
$user = $this->getUser();
$custom = $customRepository->getByUserAndId($this->getUser(), $id);
return $this->statusOk(
null,
null,
$custom
);
}
/**
* @Route(path="/api/add-to-cart", methods={"POST"})
*/
public function addToCart(Request $request, CartRepository $repository)
{
$data = $request->request->all();
$form = $this->createForm(CartType::class);
$form->submit($data);
if ($form->isSubmitted() && $form->isValid()) {
/** @var User $user */
$user = $this->getUser();
$subServices = $form->getData()['sub_services'];
$em = $this->getDoctrine()->getManager();
foreach ($subServices as $subService) {
$cart = $repository->getByUserAndSubService($user, $subService) ?: new Cart();
if ($cart->getId()) {
$cart->setCount($cart->getCount() + 1);
}
$cart->setUser($user)
->setSubService($subService);
$em->persist($cart);
}
$em->flush();
return $this->statusOk(null, null, $user);
}
$errors = FormHelper::getErrors2($form);
return $this->statusConflict($errors, ResponseCode::VALIDATION_FAIL);
}
/**
* @Route(path="/api/cart/{id}", methods={"PATCH"})
*/
public function changeCount(CartRepository $repository, Request $request, $id)
{
/** @var User $user */
$user = $this->getUser();
$cart = $repository->getByUserAndId($user, $id ?: 0);
if ($cart && $request->request->has('count')) {
$em = $this->getDoctrine()->getManager();
$count = $request->request->getInt('count');
if ($count < 1) {
$em->remove($cart);
} else {
$cart->setCount($count);
$em->persist($cart);
}
$em->flush();
}
$cart = $repository->getByUser($user);
return $this->statusOk(
null,
null,
[
'items' => $cart,
]
);
}
/**
* @Route(path="/api/booking", methods={"POST"})
*/
public function addBooking(
Request $request,
ContainerInterface $container,
SubServiceRepository $subServiceRepository,
EntityManagerInterface $em,
Fondy $fondy,
Mercure $mercure
)
{
/** @var User $user */
$user = $this->getUser();
$errors = [];
$data = $request->request->all();
$form = $this->createForm(BookingType::class);
$form->submit($data);
if ($form->isSubmitted() && $form->isValid())
{
$subService = $subServiceRepository->findOneBy(['id' => $form->getData()['sub_service']]);
$bookDate = \DateTime::createFromFormat('Y-m-d*H:i:s', $form->getData()['book_date']);
$this->guestClient = new TngGuestClient($container->getParameter('tng_api_key'));
$this->staffClient = new TngStaffClient($container->getParameter('tng_api_key'));
$this->staffClient->login($container->getParameter('tng_staff_login'), $container->getParameter('tng_staff_password'));
if($subService->getTngId() > 0 && $userSession = $this->staffClient->getUserSessionByEmail($user->getEmail()))
{
$this->guestClient->setUserSession($userSession);
// try to book
$bookData = [
'outlet_id' => $subService->getOutletId(),
'offer_id' => $subService->getTngId(),
'profile_id' => $user->getTngId(),
'comment' => "created by domosfera api",
'from' => $bookDate->format('d.m.Y H:i'),
];
if($bookId = $this->guestClient->createBooking($bookData))
{
// make cart
$total = $subService->getPrice();
$custom = new Custom();
$custom->setUser($user);
$customCart = new CustomCart();
$customCart
->setCount(1)
->setSubService($subService)
->setCustom($custom);
$em->persist($customCart);
$custom->setCost($total);
$em->persist($custom);
$em->flush();
// pay
$result = $fondy->initiatePayment(ceil($total * 100), $user->getRecToken(), 'Services_Payment_'.$custom->getId());
$custom->setOrderId($result['order_id'] ?? '')
->setStatus($result['order_status'] ?? '')
->setPaymentId($result['payment_id'] ?? '');
$em->persist($custom);
$em->flush();
//$mercure->sendMessageAboutCustom($custom);
// make booking
if($result['order_id'])
{
$tenderId = $this->getTngTenderId($user->getCardType());
$offers = $payments = [];
$customCart->setTngId($bookId);
$em->persist($customCart);
$em->flush();
$offers[] = [
'bookingId' => $bookId,
];
$payments[] = [
'tenderId' => $tenderId,
'amount' => $customCart->getSubService()->getPrice() * $customCart->getCount(),
];
if($billId = $this->guestClient->makeBill($custom->getUser()->getTngId(), $customCart->getSubService()->getOutletId(), $offers, $payments))
{
$customCart->setBillId($billId->id);
$em->persist($customCart);
$em->flush();
$custom->setStatus('payed');
$em->persist($custom);
$em->flush();
}
}
$booking = new Booking();
$booking->setTngId($bookId);
$booking->setCustomCart($customCart);
$booking->setBookDate($bookDate);
$em->persist($booking);
$em->flush();
return $this->statusOk(null, null, $booking);
}
}
}
else
{
$errors = FormHelper::getErrors2($form);
}
return $this->statusConflict($errors, ResponseCode::VALIDATION_FAIL);
}
/**
* @Route(path="/api/booking", methods={"GET"})
*/
public function getBookings(
Request $request,
BookingRepository $bookingRepository
)
{
/** @var User $user */
$user = $this->getUser();
$bookings = $bookingRepository->getByUser($user);
return $this->statusOk(
null,
null,
[
'items' => $bookings,
]
);
}
/**
* @Route(path="/api/booking/cancel/{booking_id}", methods={"GET"})
*/
public function cancelBooking(
Request $request,
BookingRepository $bookingRepository,
ContainerInterface $container,
EntityManagerInterface $em,
$booking_id
)
{
/** @var User $user */
$user = $this->getUser();
$booking = $bookingRepository->findOneBy(['id' => $booking_id]);
if($booking && $booking->getCustomCart()->getCustom()->getUser()->getId() == $user->getId())
{
$this->guestClient = new TngGuestClient($container->getParameter('tng_api_key'));
$this->staffClient = new TngStaffClient($container->getParameter('tng_api_key'));
$this->staffClient->login($container->getParameter('tng_staff_login'), $container->getParameter('tng_staff_password'));
if($userSession = $this->staffClient->getUserSessionByEmail($user->getEmail()))
{
$this->guestClient->setUserSession($userSession);
if($this->guestClient->cancelBooking($booking->getTngId()))
{
$booking->setIsCanceled(1);
$em->persist($booking);
$em->flush();
return $this->statusOk(null, null, $booking);
}
}
}
return $this->statusConflict([], ResponseCode::VALIDATION_FAIL);
}
/**
* @Route(path="/api/cart", methods={"POST"})
*/
public function initiatePayment(
Request $request,
EntityManagerInterface $em,
TranslatorInterface $translator,
CartRepository $repository,
Fondy $fondy,
Mercure $mercure
)
{
$ids = $request->get('cart_id', []);
if(!$ids || !count($ids))
return $this->statusConflict($translator->trans('cart_empty'), ResponseCode::CART_EMPTY);
if(!is_array($ids))
$ids = [$ids];
/** @var User $user */
$user = $this->getUser();
$cart = [];
foreach($ids as $id)
if($carttmp = $repository->getByUserAndId($user, $id))
$cart[] = $carttmp;
if (!count($cart)) {
return $this->statusConflict($translator->trans('cart_empty'), ResponseCode::CART_EMPTY);
}
$total = 0;
$custom = new Custom();
$custom->setUser($user);
foreach ($cart as $item) {
$subService = $item->getSubService();
$total += $subService->getPrice() * $item->getCount();
$customCart = new CustomCart();
$customCart
->setCount($item->getCount())
->setSubService($subService)
->setCustom($custom);
$em->remove($item);
$em->persist($customCart);
}
$custom->setCost($total);
$em->persist($custom);
$em->flush();
$result = $fondy->initiatePayment(ceil($total * 100), $user->getRecToken(), 'Services_Payment_'.$custom->getId());
$custom->setOrderId($result['order_id'] ?? '')
->setStatus($result['order_status'] ?? '')
->setPaymentId($result['payment_id'] ?? '');
$em->persist($custom);
$em->flush();
$mercure->sendMessageAboutCustom($custom);
return $this->statusOk(
null,
null,
[
'items' => [],
]
);
}
private function getTngTenderId($key)
{
$key = strtolower($key);
$data = [
'cash' => '1',
'room charge' => '2',
'visa' => '3',
'mastercard' => '4',
'master card' => '4',
'american express' => '5',
'americanexpress' => '5',
'dinners club' => '6',
'jcb' => '7',
'voucher' => '8',
'deposit' => '9',
];
return isset($data[$key]) ? $data[$key] : 1;
}
}