src/Controller/AccountController.php line 180

Open in your IDE?
  1. <?php
  2. /**
  3.  * Created by PhpStorm.
  4.  * User: uwethiess
  5.  * Date: 26.09.16
  6.  * Time: 14:45
  7.  */
  8. namespace App\Controller;
  9. use App\Api\ProthelisApi;
  10. use App\Entity\Order;
  11. use App\Entity\Payment;
  12. use App\Entity\User;
  13. use App\Form\DataExportForm;
  14. use App\Form\StorageTimeForm;
  15. use App\Form\UserDeleteAccountForm;
  16. use App\Form\UserUnlinkDeviceForm;
  17. use App\Form\UserEditForm;
  18. use App\Form\UserSignupForm;
  19. use App\Repository\OrderRepository;
  20. use App\Security\LoginFormAuthenticator;
  21. use App\Service\DBLogService;
  22. use App\Service\SubscriptionService;
  23. use DateTime;
  24. use Doctrine\ORM\EntityManagerInterface;
  25. use libphonenumber\PhoneNumber;
  26. use libphonenumber\PhoneNumberFormat as PhoneNumberFormatAlias;
  27. use libphonenumber\PhoneNumberUtil;
  28. use Misd\PhoneNumberBundle\Templating\Helper\PhoneNumberHelper;
  29. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  30. use Symfony\Component\HttpFoundation\RequestStack;
  31. use Symfony\Component\Routing\Annotation\Route;
  32. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  33. use Symfony\Component\Form\FormError;
  34. use Symfony\Component\HttpFoundation\RedirectResponse;
  35. use Symfony\Component\HttpFoundation\Request;
  36. use Symfony\Component\HttpFoundation\Response;
  37. use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
  38. use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
  39. use Symfony\Contracts\Translation\TranslatorInterface;
  40. class AccountController extends AbstractController
  41. {
  42.     /** @var DBLogService $dbLogService */
  43.     private $dbLogService;
  44.     /**
  45.      * @var EntityManagerInterface
  46.      */
  47.     private $entityManager;
  48.     /**
  49.      * @var GuardAuthenticatorHandler
  50.      */
  51.     private $authenticatorHandler;
  52.     /**
  53.      * @var LoginFormAuthenticator
  54.      */
  55.     private $authenticator;
  56.     /**
  57.      * @var TranslatorInterface
  58.      */
  59.     private $translator;
  60.     /**
  61.      * @var UserPasswordEncoderInterface
  62.      */
  63.     private $encoder;
  64.     private RequestStack $requestStack;
  65.     private SubscriptionService $subscriptionService;
  66.     /**
  67.      * AccountController constructor.
  68.      */
  69.     public function __construct(DBLogService $dbLogServiceEntityManagerInterface $entityManagerGuardAuthenticatorHandler $authenticatorHandlerLoginFormAuthenticator $authenticatorTranslatorInterface $translatorUserPasswordEncoderInterface $encoderRequestStack $requestStackSubscriptionService $subscriptionService)
  70.     {
  71.         $this->dbLogService $dbLogService;
  72.         $this->entityManager $entityManager;
  73.         $this->authenticatorHandler $authenticatorHandler;
  74.         $this->authenticator $authenticator;
  75.         $this->translator $translator;
  76.         $this->encoder $encoder;
  77.         $this->requestStack $requestStack;
  78.         $this->subscriptionService $subscriptionService;
  79.     }
  80.     /**
  81.      * @Route("/prothelis-info", name="consent-notification")
  82.      * @param Request $request
  83.      * @return Response
  84.      */
  85.     public function consentAction(Request $request)
  86.     {
  87.         return $this->render('account/consent-notification.html.twig');
  88.     }
  89.     /**
  90.      * @Route("/signup", name="user_signup")
  91.      * @param Request $request
  92.      * @return Response
  93.      */
  94.     public function signupAction(Request $request)
  95.     {
  96.         $form $this->createForm(UserSignupForm::class);
  97.         $form->handleRequest($request);
  98.         if ($form->isSubmitted() && $form->isValid()) {
  99.             /** @var User $user */
  100.             $user $form->getData();
  101.             $user->setIsTempUser(false);
  102.             $user->setLocale('de');
  103.             $user->setSignupDate(new DateTime());
  104.             $user->setConsentTransfer(0);
  105.             if ($user->getAddressCountry() === 'DE') {
  106.                 // vorübergehend Abo-Option nicht anbieten wegen Umstellungen zur Prothelis Tech GmbH
  107. //                $user->setTags([User::TAG_ENABLE_ABO]);
  108.                 $user->setTags(['']);
  109.             } else {
  110.                 $user->setTags(['']);
  111.             }
  112.             $registerResult $this->registerUserApi($user);
  113.             if ($registerResult === true) {
  114.                 $this->entityManager->persist($user);
  115.                 $this->entityManager->flush();
  116.                 $this->addFlash('success''Welcome ' $user->getFirstName() . ' ' $user->getLastName());
  117.                 $this->dbLogService->info('signup''success', [$registerResult$user->getId(), $user->getUsername()]);
  118.                 return $this->authenticatorHandler->authenticateUserAndHandleSuccess($user$request$this->authenticator'main');
  119.             } else {
  120.                 // api error
  121.                 $this->addFlash('error''' $registerResult);
  122.                 $this->dbLogService->info('signup''failed', [$registerResult$user->getUsername()]);
  123.             }
  124.         } else {
  125. //            dump($form->getErrors());
  126.         }
  127.         
  128.         return $this->render('activation/userform.html.twig', ['userdataForm' => $form->createView(),]);
  129.     }
  130.     
  131.     private function registerUserApi(User $user)
  132.     {
  133.         $phoneNumberUtil PhoneNumberUtil::getInstance();
  134.         $phone1 $phoneNumberUtil->format($user->getPhoneNumber(), PhoneNumberFormatAlias::INTERNATIONAL);
  135.         $phone2 '';
  136.         if ($user->getPhoneNumber2() instanceof PhoneNumber) {
  137.             $phone2 $phoneNumberUtil->format($user->getPhoneNumber2(), PhoneNumberFormatAlias::INTERNATIONAL);
  138.         }
  139.         $userdata = [
  140.             'method' => 'activation',
  141.             'username' => $user->getUsername(),
  142.             'email' => $user->getEmailAddress(),
  143.             'password' => $user->getPlainPassword(),
  144.             'password2' => $user->getPlainPassword(),
  145.             'salut' => $user->getSalutation(),
  146.             'firstname' => $user->getFirstName(),
  147.             'lastname' => $user->getLastName(),
  148.             'address' => $user->getAddressStreetNo(),
  149.             'address2' => $user->getAddressStreetAdd() . '',
  150.             'postal' => $user->getAddressPostalCode(),
  151.             'city' => $user->getAddressCity(),
  152.             'country' => $user->getAddressCountry(),
  153.             'phone1' => $phone1'phone2' => $phone2,
  154.         ];
  155.         $response ProthelisApi::postUser($userdata);
  156.         if (@$response->error) {
  157.             //error
  158.             return $this->translator->trans('profile.' $response->error) . ' ' $this->translator->trans('api.err.' $response->reason);
  159.         } else {
  160.             //success
  161.             $apiUser ProthelisApi::getUserFromApi($user->getUsername(), $user->getPlainPassword());
  162.             $this->dbLogService->debug('api''signup', ['user' => $user'apiUser' => $apiUser], nullnull);
  163.             $user->setIdApi($apiUser->getIdApi());
  164.             return true;
  165.         }
  166.     }
  167.     
  168.     /**
  169.      * @Route("/dashboard", name="user_account")
  170.      */
  171.     public function dashboardAction(Request $request)
  172.     {
  173.         $user $this->getUser();
  174.         $orders $this->entityManager->getRepository(Order::class)->findAllDefaultNotCalceledFromUser($user);
  175.         $hasDevicesWithSms count($this->entityManager->getRepository(Order::class)->findTrackersWithSms($user)) > 0;
  176. //        $apiUser = ProthelisApi::getUserById($user->getIdApi());
  177. //        $sms_total = $apiUser->sms_total ?? 0;
  178. //        $sms_used = $apiUser->sms_used ?? 0;
  179. //        $sms_remaining = $apiUser->sms_remaining ?? 0;
  180. //        dump([$sms_total, $sms_used, $sms_remaining]);
  181.         $devices = [];
  182.         foreach ($orders as $o) {
  183.             if (!isset($devices[$o->getDeviceCode()])) {
  184.                 $devices[$o->getDeviceCode()] = [
  185.                     'detail' => [],
  186.                     'orders' => [],
  187.                 ];
  188.             }
  189.             $devices[$o->getDeviceCode()]['orders'][] = $o;
  190.         }
  191.         foreach ($devices as $dk => $dv) {
  192.             $devices[$dk]['detail'] = $this->getDeviceSummary($dv['orders']);
  193.         }
  194.         $this->requestStack->getSession()->set('orderList'$devices);
  195.         $devicesList = [
  196.             'active' => [],
  197.             'inactive' => [],
  198.             'total' => 0,
  199.         ];
  200.         foreach ($devices as $device) {
  201.             if ($device['detail']['status'] === 'active' || $device['detail']['status'] === 'activating' || $device['detail']['status'] === 'processing') {
  202.                 $devicesList['active'][] = $device;
  203.             } else {
  204.                 $devicesList['inactive'][] = $device;
  205.             }
  206.             $devicesList['total']++;
  207.         }
  208.         return $this->render('account/dashboard.html.twig', [
  209.             'user' => $user,
  210.             'devices' => $devicesList,
  211.             'showExtraOrder' => $hasDevicesWithSms,
  212.         ]);
  213.     }
  214.     /**
  215.      * @Route("/device/{sn}", requirements={"sn" = "[A-Z0-9]+"}, name="device_overview")
  216.      */
  217.     public function deviceOverviewAction($snRequest $request) {
  218.         $this->entityManager $this->getDoctrine()->getManager();
  219.         $devices $this->requestStack->getSession()->get('orderList');
  220.         $orders = [];
  221.         $payments = [];
  222.         if (!$devices) {
  223.             return $this->redirectToRoute('user_account');
  224.         }
  225.         $orders = ['detail' => $devices[$sn]['detail'], 'orders' => []]; //$devices[$sn];
  226.         /** @var Order[] $allorders */
  227.         $allorders $this->entityManager->getRepository(Order::class)->findAllDefaultNotCalceledFromUser($this->getUser());
  228.         foreach ($allorders as $o) {
  229.             if ($o->getDeviceCode() == $sn) {
  230.                 $orders['orders'][] = $o;
  231.             }
  232.         }
  233.         $payments $this->entityManager->getRepository(Payment::class)->findPastByUserAndDevice($this->getUser(), $sn);
  234.         /**
  235.          * Export Form
  236.          */
  237.         $displayExportForm $this->userIsOwner($sn);
  238.         $exportForm $this->createForm(DataExportForm::class);
  239.         if ($displayExportForm) {
  240.             $exportForm->get('deviceCode')->setData($sn);
  241.             $exportForm->handleRequest($request);
  242.             $fixtime $exportForm->get('fixtime')->getData();
  243.             if ($fixtime === 'user_defined') {
  244.                 if ($exportForm->get('dateFrom')->isEmpty()) {
  245.                     $exportForm->get('dateFrom')->addError(new FormError(''));
  246.                 }
  247.                 if ($exportForm->get('dateTo')->isEmpty()) {
  248.                     $exportForm->get('dateTo')->addError(new FormError(''));
  249.                 }
  250.             }
  251.             if ($exportForm->isSubmitted() && $exportForm->isValid()) {
  252.                 switch ($fixtime) {
  253.                     case 'all':
  254.                         $date_from 'all';
  255.                         $date_to 'all';
  256.                         break;
  257.                     case 'current_month':
  258.                         $date_from date('Y-m-01 00:00:00');
  259.                         $date_to date('Y-m-01 00:00:00'strtotime('now + 1 month'));
  260.                         break;
  261.                     case 'last_month':
  262.                         $date_from date('Y-m-01 00:00:00'strtotime('now - 1 month'));
  263.                         $date_to date('Y-m-01 00:00:00');
  264.                         break;
  265.                     case 'user_defined':
  266.                         if (!empty($exportForm->get('dateFromUTC')->getData())) {
  267.                             $date_from $exportForm->get('dateFromUTC')->getData()->format('Y-m-d H:i:s');
  268.                             $date_to $exportForm->get('dateToUTC')->getData()->format('Y-m-d H:i:s');
  269.                         } else {
  270.                             $date_from $exportForm->get('dateFrom')->getData()->format('Y-m-d H:i:s');
  271.                             $date_to $exportForm->get('dateTo')->getData()->format('Y-m-d H:i:s');
  272.                         }
  273.                         break;
  274.                 }
  275. //                $this->requestStack->getSession()->getBag('exportForm_success')->clear();
  276.                 if ($exportForm->getClickedButton()->getName() === 'export_kml') {
  277.                     ProthelisApi::sendHistoryExportEmail($orders['detail']['deviceCode'], $date_from$date_to$this->getUser()->getIdApi(), 'kml');
  278.                     $this->addFlash('exportForm_success''account.export.msg_success_kml');
  279.                 } elseif ($exportForm->getClickedButton()->getName() === 'export_csv') {
  280.                     ProthelisApi::sendHistoryExportEmail($orders['detail']['deviceCode'], $date_from$date_to$this->getUser()->getIdApi(), 'csv');
  281.                     $this->addFlash('exportForm_success''account.export.msg_success_csv');
  282.                 } elseif ($exportForm->getClickedButton()->getName() === 'export_gpx') {
  283.                     ProthelisApi::sendHistoryExportEmail($orders['detail']['deviceCode'], $date_from$date_to$this->getUser()->getIdApi(), 'gpx');
  284.                     $this->addFlash('exportForm_success''account.export.msg_success_gpx');
  285.                 }
  286.             } elseif ($exportForm->isSubmitted()) {
  287.                 $this->addFlash('exportForm_error''account.export.msg_error_check_input');
  288.             }
  289.         }
  290.         /**
  291.          * Storage Time Form
  292.          */
  293. //        $device_details = ProthelisApi::getDeviceDetails($this->getUser()->getIdApi(), $orders['detail']['deviceCode'], false);
  294. //        $storageTime = $device_details->storage_days ?: 0;
  295.         $storageForm $this->createForm(StorageTimeForm::class);
  296. //        $storageForm->get('deviceCode')->setData($orders['detail']['deviceCode']);
  297. //        $storageForm->get('storageTime')->setData($storageTime);
  298. //
  299. //        $storageForm->handleRequest($request);
  300. //        if ($storageForm->isValid()) {
  301. //            $res = ProthelisApi::setDeviceProperty($sn, 'storage_days', intval($storageForm->get('storageTime')->getData()));
  302. //            if ($res == 'ok') {
  303. //                $this->addFlash('storageForm_success', 'account.storage.msg_success');
  304. //            } elseif ($storageForm->isSubmitted()) {
  305. //                $this->addFlash('storageForm_error', 'account.storage.msg_failed');
  306. //            }
  307. //        }
  308.         /**
  309.          * Delete Data form
  310.          */
  311.         $displayDeleteForm $displayExportForm;
  312.         $deviceDeleteConfirmForm $this->createForm(UserUnlinkDeviceForm::class);
  313.         if ($displayDeleteForm) {
  314.             $deviceDeleteConfirmForm->handleRequest($request);
  315.             if ($deviceDeleteConfirmForm->isSubmitted() && $deviceDeleteConfirmForm->isValid()) {
  316.                 $providedPassword $deviceDeleteConfirmForm->get('_password')->getData();
  317.                 $passwordOk $providedPassword && $this->encoder->isPasswordValid($this->getUser(), $providedPassword);
  318.                 if (!$passwordOk) {
  319.                     $this->addFlash('deviceDeleteConfirmForm_error''account.export.msg_error_check_password');
  320.                 } else {
  321.                     switch ($deviceDeleteConfirmForm->get('_choice')->getData()) {
  322.                         case 'history':
  323.                             $unlinked ProthelisApi::deleteDeviceHistoryData($orders['detail']['deviceCode'], $this->getUser()->getIdApi());
  324.                             if ($unlinked) {
  325.                                 $this->addFlash('success''account.delete_history.msg_success');
  326.                             } else {
  327.                                 $this->addFlash('error''account.delete_history.msg_error');
  328.                             }
  329.                             return $this->redirectToRoute('user_account');
  330.                             break;
  331.                         case 'unlink':
  332.                             $unlinked ProthelisApi::unlinkDeviceAndDeleteData($orders['detail']['deviceCode'], $this->getUser()->getIdApi());
  333.                             if ($unlinked) {
  334.                                 //cancel orders
  335.                                 /** @var OrderRepository $orderRepository */
  336.                                 $orderRepository $this->entityManager->getRepository(Order::class);
  337.                                 $orderRepository->cancelRemainingRuntimeOrders($orders['detail']['deviceCode'], $this->getUser());
  338.                                 $this->addFlash('success''account.unlink_device.msg_success');
  339.                             } else {
  340.                                 $this->addFlash('error''account.unlink_device.msg_error');
  341.                             }
  342.                             return $this->redirectToRoute('user_account');
  343.                             break;
  344.                         default:
  345.                     }
  346.                 }
  347.             }
  348.         }
  349.         return $this->render('account/overview_device.html.twig', [
  350.             'orders' => $orders,
  351.             'exportForm' => $exportForm->createView(),
  352.             'storageForm' => $storageForm->createView(),
  353.             'deviceDeleteConfirmForm' => $deviceDeleteConfirmForm->createView(),
  354.             'displayExportForm' => $displayExportForm,
  355.             'displayDeleteForm' => $displayDeleteForm,
  356.             'hasActiveSubscription' => $this->subscriptionService->hasActiveSubscription($sn),
  357.             'cancelDate' => $this->subscriptionService->getCancelDate($sn),
  358.             'payments' => $payments,
  359.         ]);
  360.     }
  361.     /**
  362.      * @Route("/packets/", name="extra_overview")
  363.      */
  364.     public function extraOverviewAction(Request $request)
  365.     {
  366.         $this->entityManager $this->getDoctrine()->getManager();
  367.         /** @var Order[] $orders */
  368.         $orders $this->entityManager->getRepository(Order::class)->findAllExtraFromUser($this->getUser());
  369.         $apiUser ProthelisApi::getUserById($this->getUser()->getIdApi());
  370.         $sms_total $apiUser->sms_total ?? 0;
  371.         $sms_used $apiUser->sms_used ?? 0;
  372.         $sms_remaining $apiUser->sms_remaining ?? 0;
  373.         return $this->render('account/overview_extra.html.twig', [
  374.             'orders' => $orders,
  375.             'sms'    => [
  376.                 'total' => $sms_total,
  377.                 'remaining' => $sms_remaining,
  378.             ],
  379.         ]);
  380.     }
  381.     protected function getDeviceSummary($orders) {
  382.         /** @var Order[] $orders */
  383.         $ret = [
  384.             'deviceCode' => $orders[0]->getDeviceCode(),
  385.             'dateStart' => $orders[0]->getDateStart(),
  386.             'dateEnd' => $orders[0]->getDateEnd(),
  387.             'status' => 'active',
  388.             'deviceType' => $orders[0]->getDeviceType(),
  389.         ];
  390.         $isActiveNow false;
  391.         $now = new DateTime("now");
  392.         foreach ($orders as $o) {
  393.             if ($o->getDateStart() <= $now && $o->getDateEnd() >= $now && in_array($o->getCurrentStatus(), ['active''activating'], true)) {
  394.                 $isActiveNow true;
  395.             }
  396.             if (in_array($o->getCurrentStatus(), ['active''activating'], true)) {
  397.                 $ret['dateStart'] = min($o->getDateStart(), $ret['dateStart']);
  398.                 $ret['dateEnd'] = max($o->getDateEnd(), $ret['dateEnd']);
  399.             }
  400. //            if ($o->getCurrentStatus() !== 'active') {
  401.             $ret['status'] = $o->getCurrentStatus();
  402.             /** @var User $user */
  403.             $user $this->getUser();
  404.             if ($user->getCustomer()) {
  405.                 $ret['status'] = $o->getRentalStatus();
  406.             }
  407. //            }
  408.         }
  409.         if ($isActiveNow) {
  410.             $ret['status'] = 'active';
  411.         }
  412.         return $ret;
  413.     }
  414.     
  415.     /**
  416.      * @Route("/edit", name="user_edit")
  417.      * @return Response
  418.      */
  419.     public function editAction(Request $request)
  420.     {
  421.         $userdata $this->entityManager->getRepository(User::class)->find($this->getUser()->getId());
  422.         $form $this->createForm(UserEditForm::class, $userdata);
  423.         $accountDeleteConfirmForm $this->createForm(UserDeleteAccountForm::class);
  424.         $form->handleRequest($request);
  425.         if ($form->isSubmitted() && $form->isValid()) {
  426.             /** @var User $data */
  427.             $data $form->getData();
  428. //            $this->entityManager->persist($data);
  429.             ProthelisApi::updateApiUser($data);
  430.             if ($data->getAddressCountry() === 'DE') {
  431.                 $data->addTag(User::TAG_ENABLE_ABO);
  432.             } else {
  433.                 $data->removeTag(User::TAG_ENABLE_ABO);
  434.             }
  435.             $this->entityManager->flush();
  436.             return $this->redirectToRoute('user_account');
  437.         }
  438.         $accountDeleteConfirmForm->handleRequest($request);
  439.         if ($accountDeleteConfirmForm->isSubmitted() && $accountDeleteConfirmForm->isValid()) {
  440.             $providedPassword $accountDeleteConfirmForm->get('_password')->getData();
  441.             $passwordOk $providedPassword && $this->encoder->isPasswordValid($this->getUser(), $providedPassword);
  442.             if (!$passwordOk) {
  443.                 $this->addFlash('accountDeleteConfirmForm_error''account.export.msg_error_check_password');
  444.             } else {
  445.                 /** @var User $user */
  446.                 $user $this->getUser();
  447.                 $user->setDeleteAfter(new DateTime('now +24 hours'));
  448.                 $this->entityManager->flush();
  449.                 $this->addFlash('success''account.delete_account.msg_init');
  450.             }
  451.         }
  452.         return $this->render('account/userform.html.twig', ['user' => $this->getUser(), 'userdataForm' => $form->createView(), 'accountDeleteConfirmForm' => $accountDeleteConfirmForm->createView()]);
  453.     }
  454.     /**
  455.      * @Route("/edit/abort", name="abort_deletion")
  456.      * @return Response
  457.      */
  458.     public function abortDeletionAction(Request $request)
  459.     {
  460.         /** @var User $user */
  461.         $user $this->getUser();
  462.         $user->setDeleteAfter(null);
  463.         $this->entityManager->flush();
  464.         $this->addFlash('success''account.delete_account.msg_abort');
  465.         return $this->redirectToRoute('user_edit');
  466.     }
  467.     /**
  468.      * @Route("/cancelSubscription/{sn}", requirements={"sn" = "[A-Z0-9]+"}, name="cancel_subscription")
  469.      */
  470.     public function cancelSubscriptionAction($snRequest $request)
  471.     {
  472.         $cancelDate $this->subscriptionService->getCancelDate($sn);
  473.         if (!$cancelDate) {
  474.             // no subscription
  475.             return $this->redirectToRoute('user_account');
  476.         }
  477.         $form $this->createFormBuilder()
  478.             ->add('yes'SubmitType::class, ['label' => 'account.subscription.cancel_now'])
  479.             ->getForm();
  480.         $form->handleRequest($request);
  481.         if ($form->isSubmitted() && $form->isValid()) {
  482.             $data $form->getData();
  483.             if ($this->subscriptionService->cancelSubscription($sn)) {
  484.                 $this->addFlash('success'$this->translator->trans('account.subscription.cancel_success', ['%deviceCode%' => $sn'%cancelDate%' => $cancelDate->format('d.m.Y')]));
  485.                 $this->dbLogService->info('order''cancelSubscription', ['status' => 'success''deviceCode' => $sn'userId' => $this->getUser()->getId()]);
  486.             } else {
  487.                 $this->addFlash('error'$this->translator->trans('account.subscription.cancel_failed', ['%deviceCode%' => $sn]));
  488.                 $this->dbLogService->info('order''cancelSubscription', ['status' => 'failed''deviceCode' => $sn'userId' => $this->getUser()->getId()]);
  489.             }
  490.             return $this->redirectToRoute('device_overview', ['sn' => $sn]);
  491.         }
  492.         return $this->render('account/cancel_subscription.html.twig',
  493.         [
  494.             'cancelForm' => $form->createView(),
  495.             'deviceCode' => $sn,
  496.             'cancelDate' => $cancelDate,
  497.         ]);
  498.     }
  499.     protected function userIsOwner($device_sn) {
  500.         try {
  501.             $idApi $this->getUser()->getIdApi();
  502.             $device ProthelisApi::getDevice($device_sn);
  503.             if (!$device) {
  504.                 return false;
  505.             }
  506.             foreach ($device->owners as $owner) {
  507.                 if ($owner->user_id === $idApi) {
  508.                     return true;
  509.                 }
  510.             }
  511.         } catch (\Exception $exception) {
  512.             return false;
  513.         }
  514.         return false;
  515.     }
  516. }