<?php
namespace Diplix\KMGBundle\Controller\Service;
use Cocur\Slugify\Slugify;
use Diplix\Commons\DataHandlingBundle\Entity\SysLogEntry;
use Diplix\Commons\DataHandlingBundle\Repository\SysLogRepository;
use Diplix\KMGBundle\Controller\Availability\AvailabilityController;
use Diplix\KMGBundle\Entity\Accounting\Job;
use Diplix\KMGBundle\Entity\Address;
use Diplix\KMGBundle\Entity\Availability;
use Diplix\KMGBundle\Entity\Dispatching\ChatMessage;
use Diplix\KMGBundle\Entity\Dispatching\DispatchQueueItem;
use Diplix\KMGBundle\Entity\File;
use Diplix\KMGBundle\Entity\Order;
use Diplix\KMGBundle\Entity\OrderStatus;
use Diplix\KMGBundle\Entity\PaymentType;
use Diplix\KMGBundle\Entity\PriceList;
use Diplix\KMGBundle\Entity\Role;
use Diplix\KMGBundle\Entity\User;
use Diplix\KMGBundle\Exception\OrderValidationException;
use Diplix\KMGBundle\Form\OrderForm;
use Diplix\KMGBundle\Form\Util\FormErrorsSerializer;
use Diplix\KMGBundle\Helper\ClientConfigProvider;
use Diplix\KMGBundle\PdfGeneration\JobPdf;
use Diplix\KMGBundle\PriceCalculator\AbstractPriceCalculator;
use Diplix\KMGBundle\Repository\AvailabilityRepository;
use Diplix\KMGBundle\Repository\BasicRepository;
use Diplix\KMGBundle\Repository\FileRepository;
use Diplix\KMGBundle\Service\MobileNotifier;
use Diplix\KMGBundle\Service\Notifier;
use Diplix\KMGBundle\Service\OrderHandler;
use Diplix\KMGBundle\Service\TaMiConnector;
use Doctrine\ORM\EntityManagerInterface;
use League\Flysystem\FilesystemOperator;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
class Api2Controller extends ServiceBaseController
{
public const LOG_TYPE = 'Api2';
protected function hasRole($role)
{
$R = $this->user->getRoles(true);
/** @var Role $RR */
foreach ($R as $RR)
{
/** @noinspection TypeUnsafeComparisonInspection */
if ($RR->getRole() == $role) return true;
}
return false;
}
protected function parseAndAuth(Request $request)
{
$data = $this->parseRequest($request);
$this->loadUser($data['login'],$data['password'],false);
// do not detach user -> deprecated and kills further ops which rely on objects with an association with that user (e.g. deviceTokens)
return $data;
}
protected function storeToken(array $req, $source='')
{
SysLogRepository::logMessage(
$this->managerRegistry->getConnection(),
SysLogEntry::SYS_INFO,
sprintf('User#%d reported token "%s" for platform "%s" (%s)',$this->user->getId(), $req['fcm_token']??'-',$req['platform']??'-',$source)
);
if ( (isset($req['fcm_token']) && (strlen($req['fcm_token'])>1)) )
{
$token = $req['fcm_token'];
$platform = isset($req['platform']) ? $req['platform'] : 'unknown platform';
$isNewToken = $this->userRepo->addFcmTokenToUser($this->user->getId(), $token,$platform);
$logToken = substr($token,0,4).'(...)'.substr($token,-4);
if ($isNewToken)
SysLogRepository::logMessage(
$this->managerRegistry->getConnection(),
SysLogEntry::SYS_INFO,
sprintf('User#%d stored a new FCM token "%s" for platform "%s"',$this->user->getId(),$logToken,$platform)
);
}
}
public function storeFcmTokenAction(Request $request)
{
$req = $this->parseAndAuth($request);
// auth successful at this point
$this->storeToken($req,"storeFcmTokenAction");
return new JsonResponse(['success' => true]);
}
public function __construct(
protected FileRepository $fileRepository,
protected OrderHandler $orderHandler,
protected Notifier $notifier,
protected MobileNotifier $mobileNotifier,
protected TaMiConnector $taMiConnector,
protected FilesystemOperator $uploadsFilesystem,
protected UserPasswordHasherInterface $hasher,
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
)
{
parent::__construct($this->hasher,$this->managerRegistry);
}
public function indexAction(Request $request)
{
$req = $this->parseAndAuth($request);
// auth successful at this point
$this->storeToken($req,"indexAction");
$res = [
'success' => true,
'user' => [
'firstName' =>$this->user->getFirstName(),
'lastName' =>$this->user->getLastName(),
'email' =>$this->user->getEmail(),
'id' =>$this->user->getId(),
]
];
$m = $this->user->getMember();
if ($m !== null)
{
$res['member'] = [
'name' => $m->getName(),
'number' =>$m->getNumber(),
'code' =>$m->getShortCode(),
'id' =>$m->getId()
];
}
$c = $this->user->getCustomer();
if ($c !== null)
{
$res['customer'] = [
'name' =>$c->getName(),
'number' =>$c->getCustomerNo(),
'id' =>$c->getId()
];
}
return new JsonResponse($res);
}
public static function prepare4json(&$data,$humanReadable=true)
{
$data['customer'] = $data['customer']['id'];
$data['beOwner'] = $data['beOwner']['id'];
$data['assignedTo'] = $data['assignedTo'] !== null ? $data['assignedTo']['id'] : 0;
$data['orderStatus'] = $data['orderStatus']['id'];
$data['orderTime'] = $data['orderTime']->format(self::DATE_FORMAT);
$data['paymentType'] = $humanReadable ? $data['paymentType']['name'] : $data['paymentType']['id'];;
$ft = $data['flightTime'];
$data['flightTime'] = $ft != null ? $ft->format('H:i') : null;
for ($a=0; $a< $ac=count($data['addressList']); $a++)
{
$data['addressList'][$a]['beCreated'] = $data['addressList'][$a]['beCreated']->format(self::DATE_FORMAT);
$data['addressList'][$a]['beEdited'] = $data['addressList'][$a]['beEdited'] !== null ? $data['addressList'][$a]['beEdited']->format(self::DATE_FORMAT) : null;
unset($data['addressList'][$a]['beDeleted']);
unset($data['addressList'][$a]['creditCardNo']);
unset($data['addressList'][$a]['creditCardMonth']);
unset($data['addressList'][$a]['creditCardYear']);
}
}
public function singleOrderAction(Request $request)
{
$req = $this->parseAndAuth($request);
$repo = $this->managerRegistry->getRepository(Order::class);
//if ($this->user->getMember()===null) throw new \Exception('Fetching a single order is not enabled for your account.');
$data = [];
$item = $repo->getSingleAsArray($req['id']);
if ($item!=null)
{
self::prepare4json($item);
$data[]= $item;
}
return new JsonResponse([ 'success' => true,
'data' => $data
]);
}
public function ordersAction(Request $request)
{
$req = $this->parseAndAuth($request);
// get filters owned orders
$filterStatus = array_key_exists('status',$req) ? $req['status'] : 0;
$from = (new \DateTime())->sub(new \DateInterval('P3M'));
$to = (new \DateTime())->add(new \DateInterval('P3M'));
$from = array_key_exists('from',$req) ? new \DateTime($req['from']) : $from ;
$to = array_key_exists('until',$req) ? new \DateTime($req['until']) : $to ;
$repo = $this->managerRegistry->getRepository(Order::class);
if ($this->user->getMember()!==null)
{
$data = $repo->findAllForOverview(
null,
0,
$filterStatus,
$from,
$to,
$this->user->getMember()->getId());
}
else
{
$filterUserList = $this->userRepo->findUsersISubstitute($this->user);
$filterUserList[] = $this->user;
$filterCustomerId = 0; // 0 = no additional filtering - already done through userlist
// no superadmin or orderadmin filters at the moment
$data = $repo->findAllForOverview(
$filterUserList,
$filterCustomerId,
$filterStatus,
$from,
$to);
}
// pre-process joined table fields
$ic = count($data);
for ($i=0;$i<$ic;$i++)
{
$this->prepare4json($data[$i]);
}
return new JsonResponse([ 'success' => true,
'from' => $from,
'until' => $to,
'data' => $data
]);
}
const CODE_MINE = 1;
const CODE_NOT_MINE = 2;
protected function mnLog($it,$msg,$isError=false,$details=[])
{
$itid = ($it instanceof DispatchQueueItem ? $it->getId() : ($it !== null ? (string)$it : 'null'));
$this->managerRegistry
->getRepository(SysLogEntry::class)
->log(($isError ? SysLogEntry::SYS_ERROR : SysLogEntry::SYS_INFO), MobileNotifier::LOG_TYPE, $msg, $details, 0, 0, $itid);
}
public function acceptOrDenyOrderAction(Request $request)
{
$repo = $this->managerRegistry->getRepository(Order::class);
$dqi = $this->managerRegistry->getRepository(DispatchQueueItem::class);
try {
$code = self::CODE_NOT_MINE;
$req = $this->parseAndAuth($request);
if (!in_array($req['action'],['accept','decline']))
{
throw new \Exception('Unbekannte action.');
}
$this->managerRegistry->getManager()->transactional(function(EntityManagerInterface $em) use ($repo,$dqi,$req,&$code) {
$order = null;
if (isset($req['id']))
{
$order = $repo->findOneBy(['id'=>$req['id']]);
}
else
{
$order = $repo->findOneBy(['orderId'=>$req['orderId']]);
}
$refMsg = $dqi->findOneBy(['id'=>$req['reference'] ?? 'null']);
if (($order->getAssignedTo()===null) || ($order->getAssignedTo()->getId() != $this->user->getMember()->getId()) )
{
throw new \Exception(/*var_export($req,true).*/sprintf('Diese Fahrt(#%d:%s) ist Ihnen(%s) nicht zugeordnet.',$order->getId(),$order->getOrderId(),$this->user->getMember()->getId()),self::CODE_NOT_MINE);
}
if ($req['action']==='accept')
{
$order->setAssignmentConfirmed(true, $this->user);
$order->setAssignmentStatus(Order::AS_NONE);
$code = self::CODE_MINE;
if ($refMsg!==null)
{
$refMsg->setResponse(DispatchQueueItem::R_CONFIRMED);
}
$this->mnLog($refMsg,'Fahrt angenommen');
}
else
if ($req['action']==='decline')
{
if ($order->isAssignmentConfirmed())
{
throw new \Exception('Fahrt wurde bereits bestätigt. Bitte rufen Sie an um Änderungen vorzunehmen.',self::CODE_MINE);
}
if ($order->getOrderStatus()->getId()==OrderStatus::STATUS_VERMITTELT)
{
$osOffen = $em->find(OrderStatus::class,OrderStatus::STATUS_OPEN);
$order->setOrderStatus($osOffen);
}
$order->setAssignedTo(null);
if ($order->getXchgStatus() !== Order::XCHG_RECEIVED_FROM_OTHER) // falls Fahrt von Fremdsystem darf der Status nicht geändert werden
{
$order->setXchgStatus(Order::XCHG_NONE);
}
$order->setXchgTo(null);
$order->setAssignmentStatus(Order::AS_LAST_ASSIGNMENT_DENIED);
if ($refMsg!==null)
{
$refMsg->setResponse(DispatchQueueItem::R_REFUSED);
}
$this->mnLog($refMsg,'Fahrt abgelehnt');
}
});
// TODO: notifications/orderhandler??
$order = null;
if (isset($req['id']))
{
$order = $repo->findOneBy(['id'=>$req['id']]);
}
else
{
$order = $repo->findOneBy(['orderId'=>$req['orderId']]);
}
$this->notifier->triggerOrderUpdateForMember($order); // having this line in finally() crashes since entity manager is already closed when an error occurs above
return new JsonResponse([ 'success' => true, 'mine'=>($code == self::CODE_MINE) ]);
}
catch (\Throwable $ex)
{
SysLogRepository::logMessage($this->managerRegistry->getConnection(),SysLogEntry::SYS_ERROR, 'acceptOrDenyOrderAction():'.$ex->getMessage());
return new JsonResponse([ 'success' => false, 'mine'=>($ex->getCode()==self::CODE_MINE), 'message'=>$ex->getMessage()??'' ]);
}
}
public function confirmMessageReceivedAction(Request $request)
{
try {
$req = $this->parseAndAuth($request);
$mn = $this->mobileNotifier;
$ok = $mn->confirmReceived($req['guid'],true);
return new JsonResponse([ 'success' => $ok ]);
}
catch (\Exception $ex)
{
SysLogRepository::logMessage($this->managerRegistry->getConnection(),SysLogEntry::SYS_ERROR, 'confirmMessageReceivedAction():'.$ex->getMessage());
return new JsonResponse([ 'success' => false, 'message'=>$ex->getMessage() ]);
}
}
/**
* @param $id
* @return Order
*/
protected function fetchOrderAndCheckAssignment($id)
{
return $this->fetchOrderAndCheckAssignmentByQuery(array('id' => $id));
}
/**
* @param $id
* @return Order
*/
protected function fetchOrderAndCheckAssignmentByQuery(array $predicates)
{
$repo = $this->managerRegistry->getRepository(Order::class);
/** @var Order $row */
$row = $repo->findOneBy($predicates);
if ($row === null)
{
throw new NotFoundHttpException('Invalid id: '.var_export($predicates,true));
}
if ( ($row->getAssignedTo() === null) ||($row->getAssignedTo()->getId()!= $this->user->getMember()->getId()) )
{
throw $this->createAccessDeniedException('Fahrt ist Ihnen nicht zugeordnet.');
}
return $row;
}
public function jobPdfAction(Request $request, $id)
{
$this->parseAndAuth($request);
$row = $this->fetchOrderAndCheckAssignment($id);
$pdfFile = $this->orderHandler->getJobPdf($row,$this->user,'App',true);
return $this->getDownloadResponse($pdfFile,basename($pdfFile));
}
public function updateJobByOrderIdAction(Request $request)
{
// todo merge with updateJobInfoAction()
$jr = $this->managerRegistry->getRepository(Job::class);
$fr = $this->fileRepository;
$req = $this->parseAndAuth($request);
$row = $this->fetchOrderAndCheckAssignmentByQuery(['orderId'=>$req['orderId']]);
$job = $jr->findOrCreateForOrder($row);
$pp = PropertyAccess::createPropertyAccessor();
// transform
foreach (['flightOnPositionTime',
'departureAtOriginTime',
'arrivalAtDestinationTime',] as $k)
{
if (isset($req[$k]) && $req[$k]!=null) $req[$k] = new \DateTime($req[$k]);
}
foreach (["memberExtraKm"] as $k)
{
if (isset($req[$k])&& $req[$k]!=null) $req[$k] = (int)$req[$k];
}
foreach ([ 'flightOnPositionTime',
'departureAtOriginTime',
'arrivalAtDestinationTime',
'passengerNotMet',
'taxameter',
'taxameterVat',
'extraCostName',
'extraCostPrice',
'memberExtraKm',
'confirmedByCustomerThrough',
'approvedByDriver',
'werksRundfahrt',
'extraWaitingTimeRide',
'extraWaitingTime',
'instantRideAdditionalWaitingTime',
// not allowed to set: instantRide
// not allowed to set: hasMemberExtraKm
] as $k)
{
if (array_key_exists($k,$req))
{
$pp->setValue($job,$k,$req[$k]);
}
}
if ($job->getConfirmedByCustomerThrough()>0)
{
$job->setApprovedByPassenger(true);
}
if ((array_key_exists('customerSignature',$req)) && ($req['customerSignature']!=null))
{
$stream = '';
foreach ($req['customerSignature'] as $char)
{
$stream.= chr($char);
}
$F = File::fromPsr7StreamOrString($stream, sprintf('signature_%s_%d.png',$row->getOrderId(),(new \DateTime())->getTimestamp()), $this->uploadsFilesystem,'signatures');
$fr->persistFlush($F);
$job->setCustomerSignature($F);
}
if ($job->isApprovedByDriver())
{
$jr->setApprovedByDriver($job);
$this->orderHandler->triggerJobCalculation($job);
}
$job->setLastChangeByMember(new \DateTime());
$jr->flush();
return new JsonResponse(['success' => true]);
}
public function updateJobInfoAction(Request $request, $id)
{
$jr = $this->managerRegistry->getRepository(Job::class);
$fr = $this->fileRepository;
$req = $this->parseAndAuth($request);
$row = $this->fetchOrderAndCheckAssignment($id);
$job = $jr->findOrCreateForOrder($row);
$pp = PropertyAccess::createPropertyAccessor();
// transform
foreach (['flightOnPositionTime',
'departureAtOriginTime',
'arrivalAtDestinationTime',] as $k)
{
if ($req[$k]!=null) $req[$k] = new \DateTime($req[$k]);
}
foreach ([ 'flightOnPositionTime',
'departureAtOriginTime',
'arrivalAtDestinationTime',
'passengerNotMet',
'taxameter',
'taxameterVat',
'extraCostName',
'extraCostPrice',
'memberExtraKm',
'confirmedByCustomerThrough',
'approvedByDriver'
] as $k)
{
if ($k==="memberExtraKm") $req[$k] = (int)$req[$k];
$pp->setValue($job,$k,$req[$k]);
}
if ($job->getConfirmedByCustomerThrough()>0)
{
$job->setApprovedByPassenger(true);
}
if ((array_key_exists('customerSignature',$req)) && ($req['customerSignature']!=null))
{
$stream = '';
foreach ($req['customerSignature'] as $char)
{
$stream.= chr($char);
}
$F = File::fromPsr7StreamOrString($stream, sprintf('signature_%s_%d.png',$row->getOrderId(),(new \DateTime())->getTimestamp()), $this->uploadsFilesystem,'signatures');
$fr->persistFlush($F);
$job->setCustomerSignature($F);
}
if ($job->isApprovedByDriver())
{
$this->orderHandler->triggerJobCalculation($job);
}
$job->setLastChangeByMember(new \DateTime());
$jr->flush();
return new JsonResponse(['success' => true]);
}
public function chatMessageAction(Request $request)
{
$req = $this->parseAndAuth($request);
$notifier = $this->notifier;
$repo = $this->managerRegistry->getRepository(ChatMessage::class);
$msg = ChatMessage::textFrom($this->user,$req['message']);
$repo->persistFlush($msg);
$notifier->notifyWebSocketAboutChatMessage($msg);
return new JsonResponse(['success' => true, 'ref'=>$msg->getId() ]);
}
/**
* @return PriceList
* @throws \Exception
* todo : remove redudancy
*/
protected function getDefaultPriceList()
{
$pl = $this->user->getCustomer()->getDefaultPriceList();
if ($pl === null)
{
$pl = $this->user->getCustomer()->getPriceLists()->get(0);
if ($pl === null) throw new \Exception("No priceList set");
}
return $pl;
}
protected function getDefaultPaymentType(User $user)
{
$pt = $user->getCustomer()->getDefaultPaymentType();
if ($pt === null)
{
$pt = $user->getCustomer()->getPaymentTypes()->get(0);
if ($pt === null) throw new \Exception("No paymentType set");
}
return $pt;
}
public function placeOrderAction(Request $request)
{
// TODO refactor order process (mail,tami,...) into service
$req = $this->parseAndAuth($request);
if ($request->getMethod()!==Request::METHOD_POST)
{
return new JsonResponse(['success' => false, 'errorList' => ["Use POST !"]]);
}
$orderRepo = $this->managerRegistry->getRepository(Order::class);
$tami = $this->taMiConnector;
$oh = $this->orderHandler;
// check request
$user = $this->managerRegistry->getRepository(User::class)->findOneBy(['id'=>$this->user->getId()]);
$row = $oh->getNewOrder($user,null,OrderStatus::STATUS_DRAFT);
$form = $this->createForm(OrderForm::class,$row, [
OrderForm::OPT_CUSTOMER => $this->user->getCustomer(),
OrderForm::em => $this->managerRegistry->getManager(),
OrderForm::fromService => false,
'allow_extra_fields'=>true, // omit extra fields warnings
'csrf_protection' => false
]);
// auto-inject defaults
$req["ordererName"] = $this->user->getLastName();
$req["ordererMail"] = $this->user->getEmail();
$req["ordererPhone"] = $this->user->getPhone();
$req["paymentType"] = $this->getDefaultPaymentType($this->user)->getId();
$req["priceList"] = $this->getDefaultPriceList()->getId();
$req['lastEstimatedDistance'] = 0;
$req['lastEstimatedPrice'] = 0;
// tranform origin/destination to our internal address structure
if (isset($req['origin']) && isset($req['destination']))
{
// try to parse address
/** @var Address $a1 */
$a1 = $row->getAddressList()->get(0);
/** @var Address $a2 */
$a2 = $row->getAddressList()->get(1);
if (is_array($req['origin']))
$a1->fromJson($req['origin']);
else
CustomerEndpointController::tryParseAddress($a1,$req['origin']);
if (is_array($req['destination']))
$a2->fromJson($req['destination']);
else
CustomerEndpointController::tryParseAddress($a2,$req['destination']);
$a1->setSortOrder(0);
$a2->setSortOrder(1);
$req['addressList'] = [];
$req['addressList'][0] = $a1->jsonSerialize();
$req['addressList'][1] = $a2->jsonSerialize();
$req = array_merge($req,$a1->jsonSerialize('addressList_0_'));
$req = array_merge($req,$a2->jsonSerialize('addressList_1_'));
}
else
{
// the address is supposed to be transmitted in the correct structure like it has been submitted via form
// done via prepare4json which is also used in OrderHandler::sendToPlatform
}
$xchg = isset($req['xchg'])&&($req['xchg']);
$fes = new FormErrorsSerializer();
$form->submit($req);
if ($form->isValid())
{
if ($xchg)
{
$row->setXchgStatus(Order::XCHG_RECEIVED_FROM_OTHER);
$row->setXchgOrderId( $req['original_order_id'] );
$row->setOriginOrderId( $req['original_order_id'] );
}
if ( (isset($req['commit']))&&($req['commit']== true) )
{
try {
$oh-> storeOrUpdate($row);
$oh->initiateOrder($row);
} catch (OrderValidationException $ex) {
$form->addError(new FormError($ex->getMessage()));
}
// success
if ( ($form->isValid()) && ($form->getErrors()->count() < 1))
{
SysLogRepository::logMessage(
$this->managerRegistry->getConnection(),
SysLogEntry::SYS_INFO,
sprintf('API: Order %s placed.',$row->getOrderId())
);
return new JsonResponse(['success' => true, 'data' => $row->getOrderId()]);
}
// failed
$errors = $fes->serializeFormErrors($form, true, true);
SysLogRepository::logMessage(
$this->managerRegistry->getConnection(),
SysLogEntry::SYS_INFO,
sprintf('API: Order rejected: %s',var_export($errors,true))
);
return new JsonResponse(['success' => false, 'errorList' => $errors]);
}
// simulation active
return new JsonResponse(['success' => true, 'data' => 'not committed']);
}
// form is not valid
$errors = $fes->serializeFormErrors($form, true, true);
return new JsonResponse(['success' => false, 'errorList' => $errors]);
}
public function announceReadyAction(Request $request)
{
$req = $this->parseAndAuth($request);
$tomorrow = $req['tomorrow'] === 'true';
/** @var AvailabilityRepository $repo */
$repo = $this->managerRegistry->getRepository(Availability::class);
$ret = $repo->announceReady($this->user->getMember(),$tomorrow);
return new JsonResponse(['success' => $ret, 'data' =>[]]);
}
public function cancelOrderAction(Request $request)
{
$req = $this->parseAndAuth($request);
$repo = $this->managerRegistry->getRepository(Order::class);
try
{
if ($request->getMethod()!==Request::METHOD_POST)
{
throw new MethodNotAllowedException([Request::METHOD_POST],"Use POST !");
}
if (!isset($req['orderId']))
{
throw new \RuntimeException("No orderId");
}
$row = $repo->findOneBy(["orderId"=>$req['orderId'], 'customer'=> $this->user->getCustomer()->getId()]);
if ($row === null)
{
throw new \RuntimeException('Unbekannte oder nicht zugehörige OrderId');
}
// bereits storniert -> erfolgsfall melden
if ($row->getOrderStatus()->getId() === OrderStatus::STATUS_CANCELED)
{
return new JsonResponse(['success' => true, 'data' => $row->getOrderId() . " storniert"]);
}
$oh = $this->orderHandler;
$oh->ensureThatOrderCanBeCancelled($row);
if ( (isset($req['commit']))&&($req['commit']== true) )
{
$oh->cancelOrder($row);
SysLogRepository::logMessage(
$this->managerRegistry->getConnection(),
SysLogEntry::SYS_INFO,
sprintf('API: Order %s cancelled.',$row->getOrderId())
);
return new JsonResponse(['success' => true, 'data' => $row->getOrderId() . " storniert"]);
}
else
{
return new JsonResponse(['success' => true, 'data' => 'not committed']);
}
}
catch (\Throwable $ex)
{
return new JsonResponse(['success' => false, 'errorList' => [ $ex->getMessage() ]]);
}
}
}