src/Controller/ApiController.php line 88

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\HttpFoundation\Response;
  5. use Symfony\Component\Routing\Annotation\Route;
  6. use Symfony\Component\HttpFoundation\Request;
  7. use Symfony\Component\HttpFoundation\Exception\JsonException;
  8. use App\Entity\Container;
  9. use App\Entity\Box;
  10. use App\Entity\Supply;
  11. use App\Entity\Supplier;
  12. use App\Entity\Provider;
  13. /**
  14.  * @Route("/api", name="api_")
  15.  */
  16. class ApiController extends BaseController
  17. {
  18.     /* todo: pozdeji do DB, prirazovat treba prava, atd... ted na to neni cas */
  19.     // API_KLIC => ID_KONTEJNERU
  20.     const API_KEYS = [
  21.         '123ABC123ABC123ABC' => 1,
  22.     ];
  23.     const API_OPERATIONS = [
  24.         'test',
  25.         'report-container-state',
  26.         'report-ac',
  27.         'get-ac-setting',
  28.         'report-manipulator-states',
  29.         'check-incoming-supply-box',
  30.         'find-box-for-extraction',
  31.         'empty-box-extracted-by-supplier',
  32.         'full-box-inserted-by-supplier',
  33.         'check-incoming-provider',
  34.         'check-incoming-empty-box',
  35.         'full-box-extracted-by-provider',
  36.         'empty-box-inserted-by-provider',
  37.     ];
  38.     protected Container $requestingContainer// KONTEJNER, KTERY POSILA API REQUEST, naplnuje se v preProcessApiCall()
  39.     /*
  40.      * vrati bud chybovy Response, nebo pole dat
  41.      */
  42.     private function preProcessApiCall(Request $request)
  43.     {
  44.         // header musi obsahovat platny apikey
  45.         if(!isset(self::API_KEYS[$request->headers->get('Api-Key'null)])) return $this->json(['status' => 0'msg' => 'Unauthorized'], 401);
  46.         // musi to byt json
  47.         if($request->getContentType() !== 'json') return $this->json(['status' => 0'msg' => 'Bad request - JSON only'], 400);
  48.         // kontejner podle api klice - musi byt pouzitelny
  49.         $this->requestingContainer $this->containerModel->getUsableContainer(self::API_KEYS[$request->headers->get('Api-Key'null)]);
  50.         if(!$this->requestingContainer instanceof Container) return $this->json(['status' => 0'msg' => 'Error finding usable container'], 500); // nejaka haluz, kontejner ma spravny API klic ale je najaky problem u me
  51.         // zkusime konvertovat request na pole
  52.         try {
  53.             $payload $request->toArray();
  54.         }
  55.         catch(JsonException $e) {
  56.             return $this->json(['status' => 0'msg' => 'Bad request - JSON only'], 400);
  57.         }
  58.         // musi obsahovat platny apikey -> header!
  59.         //if(!isset($payload['apiKey']) || !in_array($payload['apiKey'], self::API_KEYS)) return $this->json(['msg' => 'Unauthorized'], 401);
  60.         // musi obsahovat platnou operaci
  61.         if(!isset($payload['operation']) || !in_array($payload['operation'], self::API_OPERATIONS)) return $this->json(['status' => 0'msg' => 'Unknown operation'], 400);
  62.         // OK, to vypada dobre
  63.         return $payload;
  64.     }
  65.     /**
  66.      * @Route("/", name="root", methods={"GET", "POST"})
  67.      */
  68.     public function index(Request $request): Response
  69.     {
  70.         $data $this->preProcessApiCall($request);
  71.         if($data instanceof Response) return $data// vratilo to chybovy response, posli ho ven
  72.         // jinak jsou data OK a je v nich rozparsovany JSON
  73.         switch($data['operation'])
  74.         {
  75.             //----------------------------------------------------------------------------------------------------------------------------------------
  76.             // test ze api funguje a API klic je v poradku
  77.             case 'test' :
  78.                 return $this->json(['status' => 1'msg' => 'OK']);
  79.             //----------------------------------------------------------------------------------------------------------------------------------------
  80.             // kontejner hlasi stav bedynek - hmm co s tim... tady asi jen ulozit do databaze, ne?
  81.             case 'report-container-state' :
  82.                 if(!isset($data['slotdata'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  83.                 // ok mam, jen ulozim json stavu do DB
  84.                 if($this->containerModel->saveReportedContainerState($this->requestingContainer$data['slotdata']) === true)
  85.                 {
  86.                     return $this->json(['status' => 1'msg' => 'Stav kontejneru uložen']);
  87.                 }
  88.                 else
  89.                 {
  90.                     return $this->json(['status' => 0'msg' => 'Chyba při ukládání stavu kontejneru']);
  91.                 }
  92.             //----------------------------------------------------------------------------------------------------------------------------------------
  93.             // front na kontejneru precetl QR (zatim predpokladame Box) - pta se, co s tim
  94.             case 'check-incoming-supply-box' :
  95.                 // v parametrech musim dostat qr boxu
  96.                 if(!isset($data['qr'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  97.                 // OK mam vse co potrebuju, dalsi uz je 'application level' tj odezva uz bude vzdy 200
  98.                 // nejprve najdeme box podle qr
  99.                 $box $this->boxModel->getBoxByQr($data['qr']);
  100.                 if(!$box instanceof Box) return $this->json(['status' => 0'msg' => 'Neznámá přepravka']);
  101.                 // ok box máme, je ve správném stavu (tj v držení Supplierem)?
  102.                 $supplier $box->getSupplier();
  103.                 if($box->getState() != 100 || ! $supplier instanceof Supplier) return $this->json(['status' => 0'msg' => 'Přepravka není očekávána (špatný stav přepravky)']);
  104.                 // ok Box je v držení nějakého Suppliera, má daný Supplier na dnešek nahlášený závoz do daného Continaeru?
  105.                 $supply $this->boxModel->getTodaysSupply($this->requestingContainer$supplier);
  106.                 if(!$supply instanceof Supply) return $this->json(['status' => 0'msg' => 'Vaše dodávka není nahlášena']);
  107.                 // priznak zda se jedna o zasilku ktera je planovana cela jen do jedne zony
  108.                 $singleZone 'none';
  109.                 if($supply->getExpectedColdBoxes() == 0)
  110.                 {
  111.                     $singleZone 'W';
  112.                 }
  113.                 else
  114.                 {
  115.                     if($supply->getExpectedWarmBoxes() == 0)
  116.                     {
  117.                         $singleZone 'C';
  118.                     }
  119.                 }
  120.                 // OK máme hlášenou dodávku, hlásíme: kdo to je, jaká to je dodávka, kolik máme volna v kontejneru
  121.                 // potřebujem nahlásit: počet prázdných přepravek (W / C) a počet prázdných slotů (W / C)
  122.                 return $this->json([
  123.                     'status' => 1,
  124.                     'supplier' => $supplier->getName(),
  125.                     'supplierId' => $supplier->getId(),
  126.                     'slotStates' => $this->containerModel->getSlotStates($this->requestingContainer),
  127.                     'singleZoneSupply' => $singleZone,
  128.                 ]);
  129.             //----------------------------------------------------------------------------------------------------------------------------------------
  130.             // hledam prazdnou bedynku v dane zone
  131.             case 'find-box-for-extraction' :
  132.                 if(!isset($data['zone'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  133.                 $box $this->containerModel->findEmptyBoxInZone($this->requestingContainer$data['zone']);
  134.                 if(!$box instanceof Box) return $this->json(['status' => 0'msg' => 'V zóně nebyla nalezena prázdná přepravka']);
  135.                 return $this->json([
  136.                     'status' => 1,
  137.                     'boxQR' => $box->getQr(),
  138.                     'boxX' => $box->getData('x'),
  139.                     'boxY' => $box->getData('y'),
  140.                 ]);
  141.             //----------------------------------------------------------------------------------------------------------------------------------------
  142.             // doslo k extrakci prazdneho boxu (odebira ho supplier)
  143.             case 'empty-box-extracted-by-supplier' :
  144.                 if(!isset($data['boxQr']) || !isset($data['supplierId'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  145.                 // hledam box, ten by mel byt v kontejneru v prazdnem stavu
  146.                 $box $this->boxModel->getBoxByQr($data['boxQr']);
  147.                 if(!$box instanceof Box) return $this->json(['status' => 0'msg' => 'Z kontejneru byla vyjmuta neznámá přepravka']); // tohle se snad nemuze stat...
  148.                 // todo: mozna jeste koukat zda je ve spravnem containeru?
  149.                 // provest stavovy prechod
  150.                 if($this->boxModel->changeBoxState($box100$data['supplierId']))
  151.                 {
  152.                     return $this->json([
  153.                         'status' => 1,
  154.                     ]);
  155.                 }
  156.                 else
  157.                 {
  158.                     return $this->json([
  159.                         'status' => 0,
  160.                         'msg' => 'Chyba při změně stavu přepravky',
  161.                     ]);
  162.                 }
  163.             //----------------------------------------------------------------------------------------------------------------------------------------
  164.             // doslo k inserci plneho boxu (vklada ho supplier)
  165.             case 'full-box-inserted-by-supplier' :
  166.                 if(!isset($data['boxQr']) || !isset($data['zone']) || !isset($data['weight'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  167.                 // hledam box, ten by mel byt u daneho suppliera
  168.                 $box $this->boxModel->getBoxByQr($data['boxQr']);
  169.                 if(!$box instanceof Box) return $this->json(['status' => 0'msg' => 'Do kontejneru byla vložena neznámá přepravka']); // tohle se snad nemuze stat...
  170.                 $box->setType($data['zone']); // TODO: tady??? asi by melo byt soucasti zmeny stavu nebo nevim...
  171.                 $box->setData('weight'intval($data['weight']));
  172.                 if($this->boxModel->changeBoxState($box400$this->requestingContainer->getId()))
  173.                 {
  174.                     return $this->json([
  175.                         'status' => 1,
  176.                     ]);
  177.                 }
  178.                 else
  179.                 {
  180.                     return $this->json([
  181.                         'status' => 0,
  182.                         'msg' => 'Chyba při změně stavu přepravky',
  183.                     ]);
  184.                 }
  185.             //----------------------------------------------------------------------------------------------------------------------------------------
  186.             // autorizuje se nam provider
  187.             case 'check-incoming-provider' :
  188.                 // v parametrech musim dostat qr providera
  189.                 if(!isset($data['qr'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  190.                 $provider $this->providerModel->getProviderByQr($data['qr']);
  191.                 if(!$provider instanceof Provider) return $this->json(['status' => 0'msg' => 'Nerozpoznaný kód']);
  192.                 // ok máme providera, jsou pro něj containeru nějaké bedýnky?
  193.                 //$boxes = $this->boxModel->getBoxesInContainerForProvider($this->requestingContainer, $provider);
  194.                 // TODO: !!! ve skutecnosti takhle: !!!
  195.                 $boxesCounts $this->boxModel->countBoxesInContainerForProvider($this->requestingContainer$provider); // pocty bedynek s dodavkami ve W a C
  196.                 $slotStates $this->containerModel->getSlotStates($this->requestingContainer);
  197.                 // simulace:
  198.                 //$boxesCounts = array('W' => 2, 'C' => 2);
  199.                 //$slotStates = array('empty_warm' => 0, 'empty_cold' => 0, 'warm_with_empty' => 46, 'cold_with_empty' => 70, 'warm_with_supply' => 2, 'cold_with_supply' => 2);
  200.                 if($boxesCounts['W'] == && $boxesCounts['C'] == && $slotStates['empty_warm'] == && $slotStates['empty_cold'] == 0)
  201.                 {
  202.                     return $this->json([
  203.                         'status' => 0,
  204.                         'provider' => $provider->getName(),
  205.                         'providerId' => $provider->getId(),
  206.                         'msg' => 'Není k dispozici žádná akce (v kontejneru pro vás není zásilka a nejsou žádné prázdné pozice)'
  207.                     ]);
  208.                 }
  209.                 return $this->json([
  210.                     'status' => 1,
  211.                     'provider' => $provider->getName(),
  212.                     'providerId' => $provider->getId(),
  213.                     'slotStates' => $slotStates,
  214.                     'boxesCounts' => $boxesCounts,
  215.                 ]);
  216.             //----------------------------------------------------------------------------------------------------------------------------------------
  217.             // provider (dopravce) vklada prazdnou bedynku
  218.             case 'check-incoming-empty-box':
  219.                 // v parametrech musim dostat qr bedynky a id jiz drive 'prihlaseneho' providera
  220.                 if(!isset($data['qr']) || !isset($data['providerId'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  221.                 // overim, zda bedynka existuje a je v drzeni daneho providera
  222.                 $box $this->boxModel->getBoxByQr($data['qr']);
  223.                 if(!$box instanceof Box) return $this->json(['status' => 0'msg' => 'Neznámá přepravka']);
  224.                 // ok box máme, je ve správném stavu (tj. v držení toho správného Providera)?
  225.                 $provider $box->getProvider();
  226.                 if($box->getState() != 200 || !$provider instanceof Provider || $provider->getId() != $data['providerId']) return $this->json(['status' => 0'msg' => 'Přepravka není očekávána (špatný stav přepravky)']);
  227.                 // vse OK, empty box muzeme potencialne prijmout - BUD ho budeme vymenovat za plny box z dodavky, NEBO vkladat na prazdne misto
  228.                 // prioritu bude mit vymena za box z dodavky
  229.                 $supplyBox $this->boxModel->getOneBoxInContainerForProvider($this->requestingContainer$provider);
  230.                 if($supplyBox instanceof Box)
  231.                 {
  232.                     // ok mame box s dodavkou v kontejneru, musime najit jeho pozici v kontejneru
  233.                     $this->containerModel->findBoxInContainer($this->requestingContainer$supplyBox); // nastavuje supplyBoxu X a Y
  234.                     if( is_null($supplyBox->getData('x')) || is_null($supplyBox->getData('y')) )
  235.                     {
  236.                         return $this->json([
  237.                             'status' => 0,
  238.                             'msg' => 'Pozice boxu ' $supplyBox->getQr() . ' nebyla v kontejneru nalezena!',
  239.                         ]);
  240.                     }
  241.                     // ok, mame vse k vymene prazdneho boxu za box s dodavkou
  242.                     return $this->json([
  243.                         'status' => 1,
  244.                         'operation' => 'extract-insert',
  245.                         'zone' => $supplyBox->getType(),
  246.                         'boxQR' => $supplyBox->getQr(),
  247.                         'boxX' => $supplyBox->getData('x'),
  248.                         'boxY' => $supplyBox->getData('y'),
  249.                     ]);
  250.                 }
  251.                 // v kontejneru jsme nenalezli Box s dodavkou pro me, tak zkusime najit volne misto kam by se dala prepravka vlozit
  252.                 $coords $this->containerModel->findEmptySpaceForEmptyBox($this->requestingContainer);
  253.                 if(!empty($coords))
  254.                 {
  255.                     return $this->json([
  256.                         'status' => 1,
  257.                         'operation' => 'insert',
  258.                         'coords' => $coords,
  259.                     ]);
  260.                 }
  261.                 return $this->json([
  262.                     'status' => 0,
  263.                     'msg' => 'Kontejner nemá plné přepravky na výměnu, ani volná místa.'
  264.                 ]);
  265.             //----------------------------------------------------------------------------------------------------------------------------------------
  266.             // doslo k extrakci naplneneho boxu (odebira ho provider)
  267.             case 'full-box-extracted-by-provider' :
  268.                 if(!isset($data['boxQr']) || !isset($data['providerId'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  269.                 // hledam box, ten by mel byt v kontejneru a soucasti dodavky pro daneho providera
  270.                 $extractedBox $this->boxModel->getBoxByQr($data['boxQr']);
  271.                 if(!$extractedBox instanceof Box) return $this->json(['status' => 0'msg' => 'Z kontejneru byla vyjmuta neznámá přepravka']); // tohle se snad nemuze stat...
  272.                 if($extractedBox->getState() != 400) return $this->json(['status' => 0'msg' => 'Z kontejneru byla vyjmuta přepravka v neodpovídajícím stavu (' $extractedBox->getState() . ')']);
  273.                 $boxSupply $extractedBox->getSupply();
  274.                 if(!$boxSupply instanceof Supply) return $this->json(['status' => 0'msg' => 'Z kontejneru byla vyjmuta přepravka která nepatří k žádné dodávce']);
  275.                 $boxProvider $boxSupply->getProvider();
  276.                 if(!$boxProvider instanceof Provider) return $this->json(['status' => 0'msg' => 'Z kontejneru byla vyjmuta přepravka která nemá určeného přepravce']);
  277.                 if($boxProvider->getId() != $data['providerId']) return $this->json(['status' => 0'msg' => 'Z kontejneru byla vyjmuta přepravka která patří jinému přepravci']);
  278.                 // todo: mozna jeste koukat zda je ve spravnem containeru?
  279.                 // provest stavovy prechod
  280.                 if($this->boxModel->changeBoxState($extractedBox200$data['providerId']))
  281.                 {
  282.                     return $this->json([
  283.                         'status' => 1,
  284.                     ]);
  285.                 }
  286.                 else
  287.                 {
  288.                     return $this->json([
  289.                         'status' => 0,
  290.                         'msg' => 'Chyba při změně stavu přepravky',
  291.                     ]);
  292.                 }
  293.             //----------------------------------------------------------------------------------------------------------------------------------------
  294.             // doslo k inserci prazdneho boxu (vklada ho provider)
  295.             case 'empty-box-inserted-by-provider' :
  296.                 if(!isset($data['boxQr']) || !isset($data['zone']) || !isset($data['providerId'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  297.                 // hledam box, ten by mel byt u daneho providera
  298.                 $box $this->boxModel->getBoxByQr($data['boxQr']);
  299.                 if(!$box instanceof Box) return $this->json(['status' => 0'msg' => 'Do kontejneru byla vložena neznámá přepravka']); // tohle se snad nemuze stat...
  300.                 if($box->getState() != 200) return $this->json(['status' => 0'msg' => 'Do kontejneru byla vložena přepravka v neodpovídajícím stavu (' $box->getState() . ')']);
  301.                 if($box->getProvider()->getId() != $data['providerId']) return $this->json(['status' => 0'msg' => 'Do kontejneru byla vložena přepravka která patří jinému přepravci']);
  302.                 $box->setType($data['zone']); // TODO: tady??? asi by melo byt soucasti zmeny stavu nebo nevim...
  303.                 if($this->boxModel->changeBoxState($box300$this->requestingContainer->getId()))
  304.                 {
  305.                     return $this->json([
  306.                         'status' => 1,
  307.                         'slotStates' => $this->containerModel->getSlotStates($this->requestingContainer),
  308.                         'boxesCounts' => $this->boxModel->countBoxesInContainerForProvider($this->requestingContainer$this->providerModel->getProvider($data['providerId'])),
  309.                     ]);
  310.                 }
  311.                 else
  312.                 {
  313.                     return $this->json([
  314.                         'status' => 0,
  315.                         'msg' => 'Chyba při změně stavu přepravky',
  316.                     ]);
  317.                 }
  318.             //----------------------------------------------------------------------------------------------------------------------------------------
  319.             // kontejner hlasi stav klimatizace/topeni
  320.             case 'report-ac' :
  321.                 if(!isset($data['acData'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  322.                 // ok mam, jen ulozim json stavu do DB
  323.                 if($this->containerModel->saveReportedAC($this->requestingContainer$data['acData']) === true)
  324.                 {
  325.                     return $this->json(['status' => 1'msg' => 'Stav AC uložen']);
  326.                 }
  327.                 else
  328.                 {
  329.                     return $this->json(['status' => 0'msg' => 'Chyba při ukládání stavu AC']);
  330.                 }
  331.             //----------------------------------------------------------------------------------------------------------------------------------------
  332.             // kontejner chce vedet stav klimatizace/topeni
  333.             case 'get-ac-setting' :
  334.                 $acs $this->containerModel->getLastACSetting($this->requestingContainer);
  335.                 if(is_null($acs)) return $this->json(['status' => 0'msg' => 'Nastavení AC není k dispozici']);
  336.                 // poznamenat, ze bylo sliznuto kontejnerem
  337.                 $this->containerModel->setACSettingDownloaded($acs['id']);
  338.                 // a vratit
  339.                 return $this->json(array_merge(['status' => ], $acs));
  340.             case 'report-manipulator-states' :
  341.                 if(!isset($data['manipulatorStates'])) return $this->json(['status' => 0'msg' => 'Chybějící parametr(y)']);
  342.                 if($this->containerModel->saveReportedManipulatorsState($this->requestingContainer$data['manipulatorStates']) === true)
  343.                 {
  344.                     return $this->json(['status' => 1'msg' => 'Stavy manipulátorů uloženy']);
  345.                 }
  346.                 else
  347.                 {
  348.                     return $this->json(['status' => 0'msg' => 'Chyba při ukládání stavu manipulátorů']);
  349.                 }
  350.         }
  351.     }
  352. }