<?php
namespace App\Controller;
use App\Entity\Order;
use App\Entity\OrderItem;
use App\Entity\LifeCycle;
use App\Enums\ResponseStatusEnum;
use App\Form\OrderSearchType;
use App\Form\OrderType;
use App\Repository\CertificateRepository;
use App\Repository\HistorySendRepository;
use App\Repository\LifeCycleRepository;
use App\Repository\OrderRepository;
use App\Repository\WidgetRepository;
use App\Repository\WidgetUserRepository;
use App\Services\Contracts\OrderServiceInterface;
use App\Services\LogService\CertificateLogService;
use Doctrine\ORM\EntityManagerInterface;
use Error;
use Exception;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Validator\Constraints\Uuid;
use Symfony\Component\Validator\Validation;
use Throwable;
class OrderController extends AbstractController
{
/**
* @param Request $request
* @param OrderRepository $orderRepository
* @param WidgetUserRepository $userRepository
* @param WidgetRepository $widgetRepository
* @return Response
* @Route("/backend/orders/statistics", name="backend_order_statistics")
* @Security("is_granted('ROLE_CLIENT') or is_granted('ROLE_MERCHANT') or is_granted('ROLE_MANAGER') or is_granted('ROLE_SUPERADMINISTRATOR')")
*/
public function statistics(Request $request, OrderRepository $orderRepository, WidgetUserRepository $userRepository, WidgetRepository $widgetRepository): Response
{
$form = $this->createForm('App\Form\StatisticsSearchType');
$form->handleRequest($request);
if (!$this->isGranted('ROLE_SUPERADMINISTRATOR')) {
$user = $userRepository->find($this->getUser()->getId());
$widgets = $user->getAvailableWidgets();
} else {
$widgets = $widgetRepository->findAll();
}
$createView = $form->createView();
if(!empty($createView->children['Widget'])) {
$keys = [];
foreach ($createView->children['Widget']->vars['choices'] as $key => $choice)
foreach ($widgets as $widget)
if ($widget->getId() == $choice->value)
$keys[] = $key;
foreach ($createView->children['Widget']->vars['choices'] as $key => $row)
if (!in_array($key, $keys))
unset($createView->children['Widget']->vars['choices'][$key]);
}
return $this->render('order/statistics.html.twig', [
'statistics_search' => $createView,
'orders' => [],
'orders_count' => 0,
'amount_orders' => 0,
'average_check' => '',
'sales_count' => 0,
'get_params' => (!empty($_GET['order_search']['columns'])?$_GET['order_search']['columns']:Order::FIELDS),
'total' => 0,
'pages' => 0,
'widgets' => $createView->children['Widget']->vars['choices'],
'page' => 0,
'params' => '&'.preg_replace('/(&page|page)=[0-9]/', '', $request->getQueryString())
]);
}
/**
* @param Request $request
* @param OrderRepository $orderRepository
* @param WidgetUserRepository $userRepository
* @param CertificateRepository $certificateRepository
* @param WidgetRepository $widgetRepository
* @return Response
* @Security("is_granted('ROLE_CLIENT') or is_granted('ROLE_MERCHANT') or is_granted('ROLE_MANAGER') or is_granted('ROLE_SUPERADMINISTRATOR')")
*/
#[Route('/backend/orders/statistics_data', name: "backend_order_statistics_data", methods: ['GET'])]
public function statisticsData(Request $request, OrderRepository $orderRepository, WidgetUserRepository $userRepository, CertificateRepository $certificateRepository, WidgetRepository $widgetRepository): Response
{
$form = $this->createForm('App\Form\StatisticsSearchType');
$form->handleRequest($request);
$user = $userRepository->find($this->getUser()->getId());
$getData = $form->getData();
$getData['paymentStatus'] = ['succeeded'];
$getData['statistics'] = 1;
$result = [];
if($form->isSubmitted() && $form->isValid()) {
$result = $orderRepository->getListFilteredOrders(
$user,
$getData,
$request->get('page', 1));
}
$daysOrders = [];
$ordersCount = $certificationsCount = $ordersSum = $smsCount = $emailCount = $otherCount = $meCount = 0;
$orderItemIds = [];
foreach($result['items'] as $row){
$orderItemIds[] = $row['id'];
$dataItem = [
'amount' => $row['amount'],
'quantity' => $row['quantity'],
'sum' => $row['amount']*$row['quantity'],
'recipient_type' => $row['recipientType'],
'delivery_type' => $row['deliveryType']
];
$daysOrders['orders'][$row['createdAt']->format('Y-m-d')][] = $dataItem;
$ordersCount++;
$otherCount += ($dataItem['recipient_type'] == 'other')?1:0;
$meCount += ($dataItem['recipient_type'] == 'me')?1:0;
$certificationsCount += $dataItem['quantity'] ?? 0;
$ordersSum += $dataItem['sum'] ?? 0;
$smsCount += (isset($dataItem['delivery_type'][0]) && $dataItem['delivery_type'][0] == 'sms')?1:0;
$emailCount += (isset($dataItem['delivery_type'][0]) && $dataItem['delivery_type'][0] == 'email')?1:0;
}
$amountsCount = [];
$nominals = $certificateRepository->getCountNominalsByOrderItemIds($orderItemIds);
foreach($nominals as $nominal){
$amountsCount[$nominal['nominal']] = $nominal['count'];
}
$averageAmount = ($ordersSum && $ordersCount)?($ordersSum/$ordersCount):0;
$daysOrders['data']=[
'orders_count' => $ordersCount,
'certifications_count' => $certificationsCount,
'orders_sum' => $ordersSum,
'average_amount' => $averageAmount,
'other_count' => $otherCount,
'me_count' => $meCount,
'sms_count' => $smsCount,
'email_count' => $emailCount,
'nominals' => $amountsCount
];
return $this->json($daysOrders);
}
/**
* @param Request $request
* @param OrderRepository $orderRepository
* @param WidgetUserRepository $userRepository
* @param WidgetRepository $widgetRepository
* @param LifeCycleRepository $lifeCycleRepository
* @return Response
* @Route("/backend/orders", name="backend_order_index")
* @Security("is_granted('ROLE_CLIENT') or is_granted('ROLE_MERCHANT') or is_granted('ROLE_MANAGER') or is_granted('ROLE_SUPERADMINISTRATOR')")
*/
public function index(Request $request, OrderRepository $orderRepository, WidgetUserRepository $userRepository, WidgetRepository $widgetRepository, LifeCycleRepository $lifeCycleRepository): Response
{
$form = $this->createForm(OrderSearchType::class);
$form->handleRequest($request);
$user = $userRepository->find($this->getUser()->getId());
$errors = [];
$orderId = $form->get('orderId')->getData();
if (!empty($orderId)) {
$validator = Validation::createValidator();
$uuidConstrain = new Uuid();
$errorUid = $validator->validate($orderId, $uuidConstrain);
if (0 !== count($errorUid)){
$errors['orderId'] = 'Некорректный № заказа Виджета';
$this->addFlash('error', 'Некорректный формат № заказа Виджета');
}
}
if(0 == count($errors) && $form->isSubmitted() && $form->isValid()) {
$result = $orderRepository->getListFilteredOrders(
$user,
$form->getData(),
$request->get('page', 1));
} else {
$result = $orderRepository->getListOrdersByUser(
$user,
$request->get('page', 1)
);
}
if (!$this->isGranted('ROLE_SUPERADMINISTRATOR')) {
$user = $userRepository->find($this->getUser()->getId());
$widgets = $user->getAvailableWidgets();
} else {
$widgets = $widgetRepository->findAll();
}
$createView = $form->createView();
if(!empty($createView->children['Widget'])) {
$keys = [];
foreach ($createView->children['Widget']->vars['choices'] as $key => $choice)
foreach ($widgets as $widget)
if ($widget->getId() == $choice->value)
$keys[] = $key;
foreach ($createView->children['Widget']->vars['choices'] as $key => $row)
if (!in_array($key, $keys))
unset($createView->children['Widget']->vars['choices'][$key]);
}
foreach ($result['items'] as &$item) {
$lifeCycle = $lifeCycleRepository->findOneBy(['order_id' => $item->getId()], ['id' => 'DESC']);
$item->lifeStatus = $lifeCycle ? LifeCycle::STATUS_LIFE[$lifeCycle->getStatus()] : '';
}
return $this->render('order/report.html.twig', [
'order_search' => $createView,
'orders' => $result['items'],
'get_params' => (!empty($_GET['order_search']['columns'])?$_GET['order_search']['columns']:Order::FIELDS),
'total' => $result['total'],
'pages' => $result['pages'],
'page' => $request->get('page', 1),
'params' => '&'.preg_replace('/(&page|page)=[0-9]/', '', $request->getQueryString())
]);
}
/**
* @param Request $request
* @param OrderRepository $orderRepository
* @param WidgetUserRepository $userRepository
* @param WidgetRepository $widgetRepository
* @return Response
* @Route("/backend/orders/csv", name="backend_order_csv")
* @Security("is_granted('ROLE_CLIENT') or is_granted('ROLE_MERCHANT') or is_granted('ROLE_MANAGER') or is_granted('ROLE_SUPERADMINISTRATOR')")
*/
public function exportCSV(Request $request, OrderRepository $orderRepository, WidgetUserRepository $userRepository, WidgetRepository $widgetRepository): Response
{
$form = $this->createForm(OrderSearchType::class);
$form->handleRequest($request);
$user = $userRepository->find($this->getUser()->getId());
$pages = 1;
$items = [];
$fields_GET = (!empty($_GET['order_search']['columns'])?$_GET['order_search']['columns']:Order::FIELDS);
foreach(Order::FIELDS as $key => $row){
if(in_array($row, $fields_GET))
$fields[$key] = $row;
}
$i=0;
for ($page = 1; $page <= $pages; $page++) {
if ($form->isSubmitted() && $form->isValid()) {
$result = $orderRepository->getListFilteredOrders(
$user,
$form->getData(),
$request->get('page', $page));
} else {
$result = $orderRepository->getListOrdersByUser(
$user,
$request->get('page', $page)
);
}
$pages = $result['pages'];
if(empty($result['items'])) continue;
/** @var Order $order */
foreach($result['items'] as $order){
foreach($order->getOrderItems() as $item){
foreach($fields as $field){
switch ($field){
case 'widgetName':
$items[$i][$field] = (string) $order->getWidget()->getName();
break;
case 'createdAt':
$items[$i][$field] = $order->getCreatedAt()->format('Y-m-d H:i:s');
break;
case 'updatedAt':
$items[$i][$field] = $order->getUpdatedAt()->format('Y-m-d H:i:s');
break;
case 'recipientType':
$items[$i][$field] = $item->getRecipientType();
break;
case 'deliveryType':
$items[$i][$field] = implode(',', $item->getDeliveryType());
break;
case 'recipientName':
$items[$i][$field] = $item->getRecipientName();
break;
case 'senderName':
$items[$i][$field] = $item->getSenderName();
break;
case 'tiberiumOrderId':
$items[$i][$field] = $item->getTiberiumOrderId();
break;
case 'widgetOrderId':
$items[$i][$field] = $order->getId();
break;
case 'getStatusText':
$items[$i][$field] = $order->getStatusText();
break;
case 'senderEmail':
$items[$i][$field] = $item->getSenderEmail();
break;
case 'recipientEmail':
$items[$i][$field] = $item->getRecipientEmail();
break;
case 'paymentDataId':
$items[$i][$field] = !empty($order->getPaymentData()['id'])?$order->getPaymentData()['id']:'';
break;
case 'quantity':
$items[$i][$field] = $item->getQuantity();
break;
case 'amount':
$items[$i][$field] = $item->getAmount();
break;
case 'summ':
$items[$i][$field] = $item->getAmount()*$item->getQuantity();
break;
}
}
$i++;
}
}
}
$fields = array_flip($fields);
array_unshift($items , $fields);
$fp = fopen('php://temp', 'w');
foreach ($items as $row) {
fputcsv($fp, $row, ';');
}
rewind($fp);
$response = new Response(chr(0xEF).chr(0xBB).chr(0xBF).stream_get_contents($fp));
fclose($fp);
$response->headers->set('Content-Encoding', 'UTF-8');
$response->headers->set('Content-Type', 'application/csv; charset=UTF-8');
$response->headers->set('Content-Disposition', 'attachment; filename="orders_'.date('Y-m-d').'.csv"');
return $response;
}
/**
* @param Request $request
* @param EntityManagerInterface $entityManager
* @param CertificateLogService $certificateService
* @param Order|null $order
* @return Response
* @Route("/backend/order/{id}/edit", name="backend_order_edit")
* @Security("is_granted('ROLE_MERCHANT') or is_granted('ROLE_MANAGER') or is_granted('ROLE_CLIENT')")
*/
public function edit(Request $request, EntityManagerInterface $entityManager, CertificateLogService $certificateService, Order $order = null): Response
{
if(null === $order) {
return $this->redirectToRoute('backend_order_index');
}
$form = $this->createForm(OrderType::class, $order);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($order);
$entityManager->flush();
return $this->redirectToRoute('backend_order_edit', ['id' => $request->get('id')]);
}
$certificateGoals = $certificateService->getCertificateGoals($order);
$publicDir = $this->getParameter('aws.site');
return $this->render('order/edit.html.twig', [
'certificateGoals' => $certificateGoals,
'order_form' => $form->createView(),
'order' => $order,
'public' => $publicDir,
'cover_dir' => '/' . $order->getWidget()->getHashedId() . $this->getParameter('app.cover_dir'),
'user_files_dir' => $this->getParameter('app.user_files_dir')
]);
}
/**
* Переотправить сертификаты и отбивки по заказу
*
* @param OrderServiceInterface $orderService
* @param Order|null $order
* @return Response
* @Route("/order/{id}/send", name="order_send")
* @Security("is_granted('ROLE_MANAGER') or is_granted('ROLE_SUPERADMINISTRATOR')")
*/
public function send(OrderServiceInterface $orderService, Order $order = null): Response
{
if (!$order) {
$response['status'] = ResponseStatusEnum::error;
$response['data'] = 'OrderNotFound';
$response['message'] = 'OrderNotFound';
return $this->json($response, Response::HTTP_NOT_FOUND);
}
try {
$orderService->reSendCertificatesByOrder($order);
} catch (Throwable|Error $e) {
$response['status'] = ResponseStatusEnum::error;
$response['data'] = 'Resend Certificates Error';
$response['message'] = $e->getMessage();
return $this->json($response, Response::HTTP_UNPROCESSABLE_ENTITY);
}
$response['status'] = ResponseStatusEnum::ok;
$response['data'] = null;
$response['message'] = 'Resend Certificates Success';
return $this->json($response);
}
/**
* @param Request $request
* @param HistorySendRepository $historySendRepository
* @return Response
* @Route("/backend/order/{id}/history", name="backend_order_history_send")
* @IsGranted("ROLE_SUPERADMINISTRATOR")
*/
public function history(Request $request, HistorySendRepository $historySendRepository): Response
{
$result = $historySendRepository->findBy(['order' => $request->get('id')]);
return $this->render('order/history.html.twig', ['history' => $result]);
}
/**
* @Route("/orderItem/{id}/receipt", name="order_get_receipt")
* @Security("is_granted('ROLE_MANAGER') or is_granted('ROLE_SUPERADMINISTRATOR')")
*/
public function getOrderReceipt(OrderItem $orderItem, OrderServiceInterface $orderService): Response
{
try {
$receipt = $orderService->getReceiptLinkByOrderItem($orderItem);
} catch (Exception|Error $e) {
$error = $e->getMessage();
}
return $this->render('order/receipt.html.twig', [
'orderItem' => $orderItem,
'error' => $error ?? null,
'receipt' => $receipt ?? null,
]);
}
/**
* Пересоздать заказ поставщику (ПЦ)
*
* @Route("/order/{id}/reorder", name="order_reorder")
* @Security("is_granted('ROLE_MANAGER') or is_granted('ROLE_SUPERADMINISTRATOR')")
*/
public function reSendOrderToVendor(OrderServiceInterface $orderService, Order $order = null): Response
{
if (!$order) {
$response['status'] = ResponseStatusEnum::error;
$response['data'] = 'OrderNotFound';
$response['message'] = 'OrderNotFound';
return $this->json($response, Response::HTTP_NOT_FOUND);
}
try {
$orderService->reSendOrderToVendor($order);
} catch (Throwable|Error $e) {
$response['status'] = ResponseStatusEnum::error;
$response['data'] = 'Reorder Error';
$response['message'] = $e->getMessage();
return $this->json($response, Response::HTTP_UNPROCESSABLE_ENTITY);
}
$response['status'] = ResponseStatusEnum::ok;
$response['data'] = null;
$response['message'] = 'Reorder Success';
return $this->json($response);
}
}