src/Controller/Api/Product/GetProductForLocalTemplateController.php line 17

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Api\Product;
  3. use App\Application\Service\Product\ProductFinder;
  4. use App\Application\Service\Product\ProductReseved;
  5. use App\Entity\Idempiere\AdOrg;
  6. use App\Repository\Idempiere\AdUserRepository;
  7. use Doctrine\Persistence\ManagerRegistry;
  8. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  9. use Symfony\Component\HttpFoundation\JsonResponse;
  10. use Symfony\Component\HttpFoundation\Request;
  11. use Symfony\Component\HttpFoundation\RequestStack;
  12. use Symfony\Component\Routing\Annotation\Route;
  13. use Symfony\Component\Security\Core\Security;
  14. class GetProductForLocalTemplateController extends AbstractController
  15. {
  16.     protected $requestStack;
  17.     protected $security;
  18.     private ProductFinder $productFinder;
  19.     private ProductReseved $productReseved;
  20.     public function __construct(
  21.         ProductFinder $productFinder,
  22.         RequestStack $requestStack,
  23.         Security $security,
  24.         ProductReseved $productReseved
  25.     ) {
  26.         $this->productFinder $productFinder;
  27.         $this->requestStack $requestStack;
  28.         $this->security $security;
  29.         $this->productReseved $productReseved;
  30.     }
  31.     /**
  32.      * @Route("/api/products/", name="get_product_list", methods={"GET"})
  33.      */
  34.     public function __invoke(
  35.         Request $request,
  36.         ManagerRegistry $manager
  37.     ) {
  38.         // 1. Prepara los parámetros de la consulta a partir de la petición.
  39.         $draw max(1$request->query->getInt('draw'1));
  40.         $page max(0$request->query->getInt('start'0));
  41.         $limit max(1$request->query->getInt('length'10));
  42.         $filters $request->query->all();
  43.         $session $this->requestStack->getSession();
  44.         $user $this->security->getUser();
  45.         $organization $session->get('organization');
  46.         $RUser = new AdUserRepository($manager);
  47.         $isSalesRep false;
  48.         foreach ($RUser->findSalesrep(''$organization->getId()) as $salesRep) {
  49.             if ($salesRep->getName() == $user->getName()) {
  50.                 $isSalesRep true;
  51.             }
  52.         }
  53.         // 2. Delega la lógica de negocio al servicio de la aplicación.
  54.         $result $this->productFinder->findProductsForTemplate($filters$page$limit);
  55.         $data array_map(function ($e) use ($isSalesRep) {
  56.             $reserved $this->productReseved->execute($e['m_product_id']);
  57.             $e['reserved'] = $reserved;
  58.             $e['available'] = $e['qty_function'];
  59.             $e['available'] -= $e['reserved_in_templates'];
  60.             $e['available'] += $e['on_arrive'];
  61.             $e['label']  = $this->setColor($e['available'], !$isSalesRep);
  62.             return $e;
  63.         }, $result['data']);
  64.         // 3. Serializa y devuelve la respuesta.
  65.         return new JsonResponse([
  66.             'draw' => $draw,
  67.             'recordsTotal' => $result['pagination']['total'],
  68.             "recordsFiltered" => $result['pagination']['total'],
  69.             'data' => $data
  70.         ]);
  71.     }
  72.     private function setColor(int $valuebool $show false): string
  73.     {
  74.         $state 'off';
  75.         $label 'Sin Stock';
  76.         if ($value 500) {
  77.             $state 'green';
  78.             $label 'Disponible';
  79.         } elseif ($value >= 100) {
  80.             $state 'yellow';
  81.             $label 'Medio';
  82.         } elseif ($value >= 1) {
  83.             $state 'red';
  84.             $label 'Bajo';
  85.         }
  86.         $num $show ? (string) $value '';
  87.         return $this->renderSingleLight($state$label$num);
  88.     }
  89.     private function renderSingleLight(string $statestring $labelstring $num ''): string
  90.     {
  91.         $palette = [
  92.             'bg'     => '#1f2937',
  93.             'stroke' => '#111827',
  94.             'off'    => '#374151',
  95.             'red'    => '#ef4444',
  96.             'yellow' => '#f59e0b',
  97.             'green'  => '#10b981',
  98.             'numOff' => '#9ca3af',
  99.             'text'   => '#111827',
  100.         ];
  101.         // 1) Color de la luz
  102.         $fillMap = [
  103.             'red'    => $palette['red'],
  104.             'yellow' => $palette['yellow'],
  105.             'green'  => $palette['green'],
  106.         ];
  107.         $fill array_key_exists($state$fillMap) ? $fillMap[$state] : $palette['off'];
  108.         // 2) Texto ARIA
  109.         $ariaMap = [
  110.             'red'    => 'Semáforo: rojo activo',
  111.             'yellow' => 'Semáforo: amarillo activo',
  112.             'green'  => 'Semáforo: verde activo',
  113.         ];
  114.         $aria array_key_exists($state$ariaMap) ? $ariaMap[$state] : 'Semáforo apagado';
  115.         $numStyle $state === 'off' "fill:{$palette['numOff']};" "fill:#fff;";
  116.         $numText  $num !== ''
  117.             '<text x="40" y="45" text-anchor="middle" dominant-baseline="middle" class="num" style="' $numStyle '">' $num '</text>'
  118.             '';
  119.         return <<<SVG
  120.         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 120" width="80" height="120" role="img" aria-label="{$aria}, etiqueta {$label}">
  121.         <style>
  122.             .label{ font-family: system-ui, sans-serif; font-size: 12px; font-weight:700; }
  123.             .num{ font-family: system-ui, sans-serif; font-size:14px; font-weight:700; stroke:{$palette['stroke']}; stroke-width:.6; }
  124.         </style>
  125.         <!-- carcasa -->
  126.         <rect x="10" y="10" width="60" height="70" rx="12" fill="{$palette['bg']}" stroke="{$palette['stroke']}" stroke-width="2"/>
  127.         <!-- luz única -->
  128.         <circle cx="40" cy="45" r="18" fill="{$fill}" stroke="{$palette['stroke']}" stroke-width="2"/>
  129.         {$numText}
  130.         <!-- label -->
  131.         <text x="40" y="105" text-anchor="middle" class="label" fill="{$palette['text']}">{$label}</text>
  132.         </svg>
  133.         SVG;
  134.     }
  135. }