src/Controller/ProjectController.php line 288

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller;
  4. use App\Data\NutritionalInfo;
  5. use App\Entity\ProductionRecipe;
  6. use App\Entity\Project;
  7. use App\Entity\ProjectCalcs;
  8. use App\Entity\RawMaterial;
  9. use App\Entity\Recipe;
  10. use App\Entity\RecipeTest;
  11. use App\Entity\RecipeTestRawMaterial;
  12. use App\Entity\Trial;
  13. use Doctrine\ORM\EntityManager;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use http\Exception\InvalidArgumentException;
  16. use phpDocumentor\Reflection\DocBlock\Tags\Method;
  17. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  18. use Symfony\Component\Console\Command\Command;
  19. use Symfony\Component\DependencyInjection\Tests\Compiler\J;
  20. use Symfony\Component\HttpFoundation\JsonResponse;
  21. use Symfony\Component\HttpFoundation\RedirectResponse;
  22. use Symfony\Component\HttpFoundation\RequestStack;
  23. use Symfony\Component\HttpKernel\Exception\HttpException;
  24. use Symfony\Component\Routing\Annotation\Route;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  27. use Symfony\Component\Validator\Constraints\Json;
  28. class ProjectController extends AbstractController
  29. {
  30.     private readonly NutritionalInfo $nutricionalAmasada;
  31.     /**
  32.      * @var array[NutritionalInfo]
  33.      */
  34.     private array $nutricionalAntesHorno;
  35.     private NutritionalInfo $nutricionalCookie;
  36.     /** @var array[NutritionalInfo] */
  37.     private array $nutricionalDespuesHorno;
  38.     #[Route('/api/projects/info/{project}')]
  39.     public function getInfo(Project $project): JsonResponse
  40.     {
  41.         $testMethods = (new \ReflectionClass(RecipeTest::class))->getProperties();
  42.         $toRet = [
  43.             "@context" => '/api/contexts/Project',
  44.             '@id' => "/api/projects/{$project->getId()}",
  45.             "@type" => "Project",
  46.             "id" => $project->getId(),
  47.             "code" => $project->getCode(),
  48.             "type" => $project->getType(),
  49.             "name" => $project->getName(),
  50.             "state" => $project->getState(),
  51.             "category" => "/api/categories/{$project->getCategory()->getId()}",
  52.             "humidity" => $project->getHumidity(),
  53.             "observations" => $project->getObservations(),
  54.             "recipes" => array_map(fn(Recipe $row) => [
  55.                 '@id' => "/api/recipes/{$row->getId()}",
  56.                 'id' => $row->getId(),
  57.                 'phase' => $row->getPhase(),
  58.                 'code' => $row->getCode(),
  59.                 'baking' => $row->getBaking(),
  60.                 'type' => $row->getType(),
  61.                 'observations' => $row->getObservations(),
  62.                 'nutriscore' => [],
  63.                 'tests' => array_map(function (RecipeTest $test) use($testMethods){
  64.                     $testArray = [];
  65.                     $testMethod null;
  66.                     foreach ($testMethods as $testMethod) {
  67.                         $methodName 'get' str_replace('_'''ucwords($testMethod->name'_'));
  68.                         $methodType $testMethod->getType()?->getName();
  69.                         if (is_string($methodType) && !str_starts_with($methodType'App')) {
  70.                             $testArray[$testMethod->name] = match ($methodType) {
  71.                                 'DateTimeInterface' => $test->$methodName()?->format('Y-m-d'),
  72.                                 default => $test?->$methodName(),
  73.                             };
  74.                         }
  75.                     }
  76.                     return $testArray;
  77.                 }, $row->getRecipeTests()->toArray())
  78.             ], $project->getRecipes()->toArray()),
  79.         ];
  80.         return new JsonResponse($toRet);
  81.     }
  82.     #[Route('/api/project/trials/{project}'name'api_project_final_tests')]
  83.     public function getFinalTests(EntityManagerInterface $entityManagerProject $project): JsonResponse
  84.     {
  85.         $toRet = [];
  86.         foreach ($project->getRecipes() as $recipe) {
  87.             foreach($recipe->getRecipeTests() as $recipeTest) {
  88.                 if ($recipeTest->getFinalTest()) {
  89.                     $toRet[] = [
  90.                         'id' => $recipeTest->getId(),
  91.                         'type' => $recipeTest->getType()
  92.                     ];
  93.                 }
  94.             }
  95.         }
  96.         return new JsonResponse($toRet);
  97.     }
  98.     /**
  99.      * Obtiene la información del valor de nutriscore y el precio del producto.
  100.      * Se llama en la ventana de presentación de la información del producto
  101.      */
  102.     #[Route('/api/projects/calc-info/{project}'name'api_project_get_calc_info')]
  103.     public function calcInfo(Project $project): JsonResponse
  104.     {
  105.         $calcs $project->getProjectCalcs();
  106.         if ($calcs) {
  107.             return new JsonResponse([
  108.                 'nutriscore' => [
  109.                     'value' => $calcs->getNutriscoreProductoValor(),
  110.                     'letter' => $calcs->getNutriscoreProductoLetra(),
  111.                 ],
  112.                 'price' => [
  113.                     'amasada' => $calcs->getCosteAmasada(),
  114.                     'total' => $calcs->getCosteProductoTerminado(),
  115.                 ]
  116.             ]);
  117.         } else {
  118.             return new JsonResponse([]);
  119.         }
  120.     }
  121.     #[Route('/api/projects/finished-nutritional-info/{project}'name'api_project_get_finished_nutritional_info')]
  122.     public function finishedNutritionalInfo(Project $project): JsonResponse
  123.     {
  124.         $calcs $project->getProjectCalcs();
  125.         if ($calcs) {
  126.             return new JsonResponse($calcs->getInformacionNutricionalProducto());
  127.         }
  128.         return new JsonResponse([]);
  129.     }
  130.     #[Route('/api/projects/close/{project}'name'api_close_project'methods: ["PATCH"])]
  131.     public function closeProject(EntityManagerInterface $entityManagerProject $project): JsonResponse
  132.     {
  133.         $recipeTypes = [
  134.             'Amasado' => false,
  135.             'Topping' => false,
  136.             'Relleno' => false,
  137.             'Cobertura' => false,
  138.         ];
  139.         $recipes $project->getRecipes();
  140.         foreach ($recipes as $recipe) {
  141.             $type $recipe->getType();
  142.             $recipeTypes[$type] = true;
  143.         }
  144.         $project->setAmasado($recipeTypes['Amasado']);
  145.         $project->setTopping($recipeTypes['Topping']);
  146.         $project->setRelleno($recipeTypes['Relleno']);
  147.         $project->setCobertura($recipeTypes['Cobertura']);
  148.         $project->setState('Terminado');
  149.         $entityManager->persist($project);
  150.         $entityManager->flush();
  151.         return new JsonResponse($recipeTypes);
  152.     }
  153.     #[Route('/api/projects/recipe_ingredients_info/{project}'name'api_recipe_ingredients_info')]
  154.     public function ingredients(Project $project): JsonResponse
  155.     {
  156.         $calcs $project->getProjectCalcs();
  157.         if ($calcs) {
  158.             return new JsonResponse([
  159.                 'cookie' => $calcs->getIngredientesCookie(),
  160.                 'totalPesoCookie' => $calcs->getTotalPesoCookie(),
  161.                 'humedadHorneado' => $calcs->getHumedadHorneado(),
  162.                 'perdidaEstimada' => $calcs->getPerdidaEstimada(),
  163.                 'perdidaEstimadaPorcentaje' => $calcs->getPerdidaEstimadaPorcentaje(),
  164.                 'totalHorneado' => $calcs->getTotalHorneado(),
  165.                 'humedadGalleta' => $calcs->getHumedadGalleta(),
  166.                 'terminado' => $calcs->getIngredientesProductoTerminado(),
  167.             ]);
  168.         } else {
  169.             return new JsonResponse([]);
  170.         }
  171.     }
  172.     #[Route('/api/projects/list_costs/{project}'name'api_project_costs')]
  173.     public function listProjectCosts(Project $project): JsonResponse
  174.     {
  175.         $calcs $project->getProjectCalcs();
  176.         if ($calcs) {
  177.             return new JsonResponse([
  178.                 'amasada' => array_values($calcs->getCostesAmasada()),
  179.                 'despuesHorno' => $calcs->getCostesDespuesHorno(),
  180.             ]);
  181.         } else {
  182.             return new JsonResponse([]);
  183.         }
  184.     }
  185.     #[Route('/api/projects/list_materials/{project}'name'api_project_list_materials')]
  186.     public function listProjectMaterials(EntityManagerInterface $entityManagerProject $project): JsonResponse
  187.     {
  188.         $rawMaterials = [];
  189.         $totalWeight 0;
  190.         $ingredientesProductoTerminado $project->getProjectCalcs()?->getIngredientesProductoTerminado();
  191.         $rawMaterialsEntity $entityManager->getRepository(RawMaterial::class);
  192.         if ($ingredientesProductoTerminado) {
  193.             foreach ($ingredientesProductoTerminado as $ingrediente) {
  194.                 /** @var RawMaterial $material */
  195.                 $material $rawMaterialsEntity->findOneBy(['id' => $ingrediente[4]]);
  196.                 $rawMaterials[$material->getId()] = [
  197.                     'id' => $material->getId(),
  198.                     'code' => $material->getCode(),
  199.                     'name' => $material->getName(),
  200.                     'marketName' => $material->getPublicName(),
  201.                     'quantity' => $ingrediente[3] / 1000// <- a Kg,
  202.                     'raw_cost' => $material->getPrice(),
  203.                     'percentage' => 0
  204.                 ];
  205.                 $totalWeight += $ingrediente[3];
  206.             }
  207.             return new JsonResponse(array_map(function($r) use ($totalWeight) {
  208.                 $r['percentage'] = $r['quantity'] / $totalWeight 1000;
  209.                 $r['cost'] = $r['percentage'] * $r['raw_cost'];
  210.                 return $r;
  211.             }, $rawMaterials));
  212.         } else {
  213.                 return new JsonResponse([]);
  214.         }
  215.     }
  216.     /**
  217.      * Crea nuevas pruebas finales para las recetas en producción así como un ensayo usando esas pruebas
  218.      */
  219.     #[Route('/api/projects/production-recipes/{project}'name'api_project_create_production_recipes'methods: ["POST"])]
  220.     public function createProductionRecipes(EntityManagerInterface $entityManagerProject $project): JsonResponse
  221.     {
  222.         $params json_decode(file_get_contents('php://input'), true512JSON_THROW_ON_ERROR);
  223.         $recetasFinalesProyecto $entityManager->getRepository(Project::class)->getFinalRecipesIds($project->getId());
  224.         //var_dump($recetasFinalesProyecto);
  225.         foreach ($recetasFinalesProyecto as $idReceta) {
  226.             //echo "Comprando {$idReceta}\n";
  227.             if (array_search($idRecetaarray_column($params'id')) === false) {
  228.                 return new JsonResponse([], \Symfony\Component\HttpFoundation\Response::HTTP_SERVICE_UNAVAILABLE);
  229.             }
  230.         }
  231.         //return new JsonResponse(['msg' => 'Todas las recetas encontradas']);
  232.         $entityManager->getRepository(Project::class)->createRecipes($project->getId(), $params);
  233.         return new JsonResponse([], \Symfony\Component\HttpFoundation\Response::HTTP_CREATED);
  234.     }
  235.     #[Route('/api/list/by-category'name'api_projects_by_category')]
  236.     public function listByType(EntityManagerInterface $entityManager): JsonResponse
  237.     {
  238.         return new JsonResponse($entityManager->getRepository(Project::class)->getListado(), \Symfony\Component\HttpFoundation\Response::HTTP_OK);
  239.     }
  240.     #[Route('/api/list/by-category-dates/{fechaInicio1}/{fechaFin1}/{fechaInicio2}/{fechaFin2}')]
  241.     public function listByTypeAndDate(EntityManagerInterface $entityManagerstring $fechaInicio1string $fechaFin1string $fechaInicio2string $fechaFin2): \Symfony\Component\HttpFoundation\Response
  242.     {
  243.         $projectRepo $entityManager->getRepository(Project::class);
  244.         return new JsonResponse([
  245.             'segment1' => $projectRepo->getListadoEntre($fechaInicio1$fechaFin1),
  246.             'segment2' => $projectRepo->getListadoEntre($fechaInicio2$fechaFin2),
  247.         ]);
  248.     }
  249.     /**
  250.      * Obtiene la lista de recetas finales de un proyecto así como los materiales de las que está compuesto
  251.      */
  252.     #[Route('/api/projects/production-recipes/{project}'name'api_project_get_production_recipes'methods: ["GET"])]
  253.     public function productionRecipes(EntityManagerInterface $entityManagerint $project): JsonResponse
  254.     {
  255.         return new JsonResponse(
  256.             $entityManager->getRepository(Project::class)->getProductionRecipes($project)
  257.         );
  258.     }
  259.     /**
  260.      *
  261.      * @todo Convertir las sentencias de Doctrine a una SQL
  262.      *
  263.      */
  264.     #[Route('/api/projects/raw-material-resume/{project}'name'api_raw_material_resume')]
  265.     public function rawMaterialsResume(EntityManagerInterface $entityManagerProject $project): JsonResponse
  266.     {
  267.         $rawMaterials = [];
  268.         $totalWeight 0;
  269.         // Compruebo si se ha guardado ya.
  270.         $productionRecipe $project->getProductionRecipe();
  271.         if (null !== $productionRecipe) {
  272.             return new JsonResponse([
  273.                 'materials' => $productionRecipe->getRawMaterials(),
  274.                 'checklist' => $productionRecipe->getCheckList(),
  275.             ]);
  276.         } else {
  277.             $recipes $project->getRecipes();
  278.             $rawMaterialsEntity $entityManager->getRepository(RecipeTestRawMaterial::class);
  279.             $recipeTestsEntity $entityManager->getRepository(RecipeTest::class);
  280.             foreach ($recipes as $recipe) {
  281.                 // Sí, no se hace automático
  282.                 $recipesTests $recipeTestsEntity->findBy([
  283.                     'recipe' => $recipe,
  284.                     'finalTest' => true,
  285.                 ]);
  286.                 if (count($recipesTests) > 0) {
  287.                     $testRawMaterials $rawMaterialsEntity->findBy([
  288.                         'recipeTest' => $recipesTests[0]
  289.                     ]);
  290.                     /** @var RecipeTestRawMaterial $testRawMaterial */
  291.                     foreach ($testRawMaterials as $testRawMaterial) {
  292.                         $material $testRawMaterial->getRawMaterial();
  293.                         $materialId $material->getId();
  294.                         if (!isset($rawMaterials[$materialId])) {
  295.                             $rawMaterials[$materialId] = [
  296.                                 'id' => $materialId,
  297.                                 'code' => $material->getCode(),
  298.                                 'name' => $material->getName(),
  299.                                 'marketName' => $material->getPublicName(),
  300.                                 'phases' => [],
  301.                                 'quantity' => 0,
  302.                                 'percentage' => 0,
  303.                                 'roundQuantity' => 0,
  304.                                 'roundPercentage' => 0,
  305.                             ];
  306.                         }
  307.                         $quantity $testRawMaterial->getQuantity() / 1000;
  308.                         $rawMaterials[$materialId]['quantity'] += $quantity;
  309.                         $rawMaterials[$materialId]['roundQuantity'] = $rawMaterials[$materialId]['quantity'];
  310.                         $totalWeight += $quantity;
  311.                         $rawMaterials[$materialId]['phases'][] = $testRawMaterial->getPhase()->getCode();
  312.                     }
  313.                 }
  314.             }
  315.             return new JsonResponse([
  316.                 'checklist' => [
  317.                     'diagrama' => false,
  318.                     'diagramaNombre' => '',
  319.                     'etapaNueva' => false,
  320.                     'etapaNombre' => '',
  321.                     'riesgos' => false,
  322.                     'riesgosNombres' => '',
  323.                     'pcc' => false,
  324.                     'pccNombre' => '',
  325.                     'otros' => false,
  326.                     'otrosNombre' => '',
  327.                     'ingredientesAlergenos' => false,
  328.                     'alergenosPresentes' => '',
  329.                     'trazas' => '',
  330.                     'nuevos' => '',
  331.                     'vidaUtil' => '',
  332.                 ],
  333.                 'materials' => array_values(
  334.                     array_map(function ($row) use ($totalWeight) {
  335.                         $row['percentage'] = sprintf('%01.2f', (100 $row['quantity']) / $totalWeight);
  336.                         $row['roundPercentage'] = $row['percentage'];
  337.                         return $row;
  338.                     }, $rawMaterials)
  339.                 )
  340.             ]);
  341.         }
  342.     }
  343.     /**
  344.      * @throws \HttpException
  345.      * @throws \JsonException
  346.      */
  347.     #[Route('/api/projects/production-checklist/{project}'name"api_save_production_recipe_checklist"methods: ["POST"])]
  348.     public function saveProductionRecipe(EntityManagerInterface $entityManagerProject $project): JsonResponse
  349.     {
  350.         $params json_decode(file_get_contents('php://input'), true512JSON_THROW_ON_ERROR);
  351.         if (isset($params['checklist'])) {
  352.             $productionRecipe $entityManager->getRepository(ProductionRecipe::class)->findOneBy(
  353.                 [
  354.                     'project' => $project
  355.                 ]
  356.             );
  357.             if (!$productionRecipe) {
  358.                 $productionRecipe = new ProductionRecipe();
  359.                 $productionRecipe->setProject($project);
  360.             }
  361.             $productionRecipe->setCheckList($params['checklist']);
  362.             $entityManager->persist($productionRecipe);
  363.             $entityManager->flush();
  364.             return new JsonResponse([]);
  365.         } else {
  366.             throw new HttpException(500,"Not valid params");
  367.         }
  368.     }
  369.     #[Route('/api/projects/{project}/print-final-trial'name'api_project_print_final_trial'methods: ["GET"])]
  370.     public function printFinalTrial(EntityManagerInterface $entityManagerProject $project): RedirectResponse
  371.     {
  372.         $trial $entityManager->getRepository(Trial::class)->findOneBy([
  373.             'project' => $project,
  374.             'finalTrial' => true
  375.         ]);
  376.         if (!$trial) {
  377.             $trials $entityManager->getRepository(Trial::class)->findBy([
  378.                 'project' => $project,
  379.             ], [
  380.                'id' => 'DESC'
  381.             ]);
  382.             if (count($trials) > 0) {
  383.                 $trial $trials[0];
  384.             }
  385.         }
  386.         if ($trial) {
  387.             return $this->redirectToRoute('api_print_trial', ['trial' => $trial->getId()]);
  388.         }
  389.         throw new \Exception('El proyecto no tiene ensayo final'403);
  390.     }
  391.     #[Route('/api/projects/production-recipe/{project}'name"api_get_production_recipe"methods: ["GET"])]
  392.     public function productionRecipe(EntityManagerInterface $entityManagerProject $project): JsonResponse
  393.     {
  394.         $toRet = [
  395.             'materials' => null,
  396.             'checklist' => null
  397.         ];
  398.         /** @var ProductionRecipe $productionRecipe */
  399.         $productionRecipe $entityManager->getRepository(ProductionRecipe::class)->findOneBy([
  400.             'project' => $project
  401.         ]);
  402.         if ($productionRecipe) {
  403.             $toRet['materials'] = $productionRecipe->getRawMaterials();
  404.             $toRet['checklist'] = $productionRecipe->getCheckList();
  405.         }
  406.         return new JsonResponse($toRet);
  407.     }
  408.     /**
  409.      * Calcula todos los valores del proyecto solicitado.
  410.      * Guarda los resultados en la entidad ProjectCalcs
  411.      * Devuelve el nutriscore final del cálculo.
  412.      *
  413.      * @todo Hay que refactorizar esto MUCHO
  414.      */
  415.     #[Route('/api/projects/calculate/{project}'name'api_project_calculate_all'methods: ['GET'])]
  416.     public function calculate(EntityManagerInterface $entityManagerProject $project): JsonResponse
  417.     {
  418.         $costes = [];
  419.         $projectCalcs $project->getProjectCalcs();
  420.         if ($projectCalcs === null) {
  421.             $projectCalcs = new ProjectCalcs();
  422.             $project->setProjectCalcs($projectCalcs);
  423.         }
  424.         $projectCalcs->setCreation(new \DateTime());
  425.         $MaterialesUsados = [];
  426.         // Primero se identifican las recetas que vienen antes del horno
  427.         $beforeOvenKneading null;
  428.         $beforeOvenOther = [];
  429.         $afterOven = [];
  430.         /** @var Recipe $recipe */
  431.         foreach ($project->getRecipes() as $recipe) {
  432.             if ($recipe->getPhase() === 0) {
  433.                 if ($recipe->getType() === 'Amasado') {
  434.                     $beforeOvenKneading $recipe;
  435.                 } else {
  436.                     $beforeOvenOther[] = $recipe;
  437.                 }
  438.             } else {
  439.                 $afterOven[] = $recipe;
  440.             }
  441.         }
  442.         // Si no hay amasado no continuamos
  443.         if ($beforeOvenKneading === null) {
  444.             //$io->error("Este proyecto no tiene ninguna masa antes de horno");
  445.             throw new HttpException(501'Proyecto incompleto');
  446.         }
  447.         $recipeTestRawMaterialRepository $entityManager->getRepository(RecipeTestRawMaterial::class);
  448.         // Estas son las recetas después del horno.
  449.         // Buscamos los tests finales para estas
  450.         $afterOvenTests = [];
  451.         $afterOvenBakingPercentage = [];
  452.         foreach ($afterOven as $recipe) {
  453.             $afterOvenBakingPercentage[] = $recipe->getBaking();
  454.             /** @var RecipeTest $recipeTest */
  455.             foreach ($recipe->getRecipeTests() as $recipeTest) {
  456.                 if ($recipeTest->getFinalTest() === true) {
  457.                     $afterOvenTests[] = $recipeTest;
  458.                 }
  459.             }
  460.         }
  461.         unset ($afterOven);
  462.         // Obtenemos los detalles de la fase final del amasado
  463.         $kneadingRecipeTest null;
  464.         foreach ($beforeOvenKneading->getRecipeTests() as $recipeTest) {
  465.             if ($recipeTest->getFinalTest() === true) {
  466.                 $kneadingRecipeTest $recipeTest;
  467.                 break;
  468.             }
  469.         }
  470.         $beforeOvenTests = [];
  471.         //$io->note("Número de recetas adicionales antes de horno: " . \count($beforeOvenOther));
  472.         foreach ($beforeOvenOther as $recipe) {
  473.             /** @var RecipeTest $recipeTest */
  474.             foreach ($recipe->getRecipeTests() as $recipeTest) {
  475.                 if ($recipeTest->getFinalTest() === true) {
  476.                     $beforeOvenTests[] = $recipeTest;
  477.                     //$io->note("Porcentaje " . $recipe->getBaking());
  478.                 }
  479.             }
  480.         }
  481.         if ($kneadingRecipeTest === null) {
  482.             throw new HttpException(501'No hay ningún test definido como final en la receta de amasado');
  483.         }
  484.         // Cálculos de porcentajes para los totales antes de horno
  485.         $totalPercentageBeforeOven 0;
  486.         $N4 0$N5 0$N6 0;
  487.         $M3 100$M4 0$M5 0$M6 0;
  488.         $porcentajesRecetas  array_fill(0\count($beforeOvenTests), 0);
  489.         $pesosInicialesRecetas array_fill(0\count($beforeOvenTests), 0);
  490.         $pesoRelacionAmasada array_fill(0\count($beforeOvenTests), 0);
  491.         if (\count($beforeOvenTests) > 0) {
  492.             $porcentajesRecetas[0] = $N4 $beforeOvenOther[0]->getBaking() / 100;
  493.             $M4 $M3 $N4 / ($N4);
  494.         }
  495.         if (\count($beforeOvenTests) > 1) {
  496.             $porcentajesRecetas[1] = $N5 $beforeOvenOther[1]->getBaking() / 100;
  497.             $M5 = ($M3+$M4)*$N5/(1-$N5);
  498.         }
  499.         if (\count($beforeOvenTests) > 2) {
  500.             $porcentajesRecetas[2] = $N6 $beforeOvenOther[2]->getBaking() / 100;
  501.             $M6 = ($M3+$M4+$M5)*$N6/(1-$N6);
  502.         }
  503.         $M7 $M3 $M4 $M5 $M6;
  504.         //var_dump($porcentajesRecetas);
  505.         /** Obtención de detalles de la masa para los cálculos del resto */
  506.         // Materiales de la receta masa
  507.         $materialesAmasado $recipeTestRawMaterialRepository->findBy(['recipeTest' => $kneadingRecipeTest]);
  508.         // Porcentaje amasado
  509.         $pesoAmasada array_reduce($materialesAmasado, fn($akk$row)=> $akk $row->getQuantity(), 0);
  510.         $J17 $beforeOvenKneading->getBaking() / 100//$M3 / $M7;
  511.         $recipesBeforeOvenCalcs = [];
  512.         $recipesAfterOvenCalcs = [];
  513.         $costes['before'] = [];
  514.         $costes['before']['others'] = [];
  515.         /** INGREDIENTES ANTES DE HORNO */
  516.         $BDIngredientesAntesHorno = [];
  517.         foreach ($beforeOvenTests as $key => $test) {
  518.             $recipeType $test->getRecipe()->getType();
  519.             $costes['before']['others'][$recipeType] = [];
  520.             $this->nutricionalAntesHorno[$recipeType] = new NutritionalInfo();
  521.             $materials $recipeTestRawMaterialRepository->findBy(['recipeTest' => $test]);
  522.             $pesosInicialesRecetas[$key] = array_reduce($materials, fn($akk$row)=> $akk $row->getQuantity(), 0);
  523.             // Sumatoria receta para una amasada [Total Masa Amasada * % Baking Receta / % Baking Masa Amasada]
  524.             $pesoRelacionAmasada[$key] = $pesoAmasada $porcentajesRecetas[$key] / $J17;
  525.             //echo "Peso relación con la amasada para la receta {$key} => {$pesoAmasada} * {$porcentajesRecetas[$key]} / {$J17} => {$pesoRelacionAmasada[$key]}\n";
  526.             //echo "Peso inicial de la receta {$key}: {$pesosInicialesRecetas[$key]}\n";
  527.             $nombreTipo $test->getRecipe()->getType();
  528.             $BDIngredientesAntesHorno[$nombreTipo] = [];
  529.             /** @var RecipeTestRawMaterial $material */
  530.             foreach($materials as $material) {
  531.                 $quantity $material->getQuantity();
  532.                 $rawMaterial $material->getRawMaterial();
  533.                 if (!isset($MaterialesUsados[$rawMaterial->getId()])) {
  534.                     $MaterialesUsados[$rawMaterial->getId()] = $rawMaterial;
  535.                 }
  536.                 // Se aplica el índice de corrección según los porcentajes de masa
  537.                 $quantityKneaded $quantity $pesoRelacionAmasada[$key] / $pesosInicialesRecetas[$key];
  538.                 $recipesBeforeOvenCalcs[$rawMaterial->getId()] = [$rawMaterial->getName(), $quantity$quantity 1000$quantity $pesosInicialesRecetas[$key], $quantityKneaded$quantityKneaded 1000];
  539.                 $BDIngredientesAntesHorno[$nombreTipo][] = $recipesBeforeOvenCalcs[$rawMaterial->getId()];
  540.                 /*echo "Información calculada para el material ", $rawMaterial->getName(), ":\n";
  541.                 var_dump($recipesBeforeOvenCalcs[$rawMaterial->getId()]);
  542.                 echo "\n\n";*/
  543.                 $costes['before']['others'][$recipeType][$rawMaterial->getId()] = [$rawMaterial->getName(), $quantity $pesosInicialesRecetas[$key], $rawMaterial->getPrice(), $rawMaterial->getPrice() * ($quantity $pesosInicialesRecetas[$key])];
  544.                 $this->nutricionalAntesHorno[$recipeType]->addRawMaterial($rawMaterial$quantity $pesosInicialesRecetas[$key]);
  545.             }
  546.         }
  547.         $projectCalcs->setIngredientesAntesHorno($BDIngredientesAntesHorno);
  548.         /** FIN INGREDIENTES ANTES DE HORNO */
  549.         /** INGREDIENTES DE LA MASA */
  550.         // Empezamos la cookie con la masa de amasado
  551.         $cookie = [];
  552.         $costes['before']['amasada'] = [];
  553.         foreach($materialesAmasado as $material) {
  554.             $rawMaterial $material->getRawMaterial();
  555.             if (!isset($MaterialesUsados[$rawMaterial->getId()])) {
  556.                 $MaterialesUsados[$rawMaterial->getId()] = $rawMaterial;
  557.             }
  558.             $quantity $material->getQuantity();
  559.             $cookie[$rawMaterial->getId()] = [$rawMaterial->getName(), $quantity$quantity 1000$quantity $pesoAmasada];
  560.             $costes['before']['amasada'][$rawMaterial->getId()] = [$rawMaterial->getName(), $quantity $pesoAmasada$rawMaterial->getPrice(), ($quantity $pesoAmasada) * $rawMaterial->getPrice()];
  561.         }
  562.         //  $cookieOriginal = $cookie;
  563.         $projectCalcs->setIngredientesAmasada($cookie);
  564.         /** FIN INGREDIENTES DE LA MASA */
  565.         /** INGREDIENTES DE LA GALLETA */
  566.         // Creamos la receta combinando los distintos materiales de las recetas de horno
  567.         foreach ($recipesBeforeOvenCalcs as $id => $otherRecipe) {
  568.             if (isset($cookie[$id])) {
  569.                 $cookie[$id][1] += $otherRecipe[4];
  570.                 $cookie[$id][2] += $otherRecipe[5];
  571.             } else {
  572.                 $cookie[$id] = [$otherRecipe[0], $otherRecipe[4], $otherRecipe[5], $otherRecipe[3],];
  573.             }
  574.         }
  575.         $cookieOriginal $cookie;
  576.         // Ahora calculamos el total de cada material quitándole la humedad
  577.         $sumaHorneado 0;
  578.         $this->nutricionalCookie = new NutritionalInfo();
  579.         foreach($cookie as $idMaterialCookie => $materialCookie) {
  580.             $cookie[$idMaterialCookie][1] = ($materialCookie[1] * (100 $MaterialesUsados[$idMaterialCookie]->getHumidity()) / 100) * ((100 $MaterialesUsados[$idMaterialCookie]->getLostVolatilization()) / 100);
  581.             $cookie[$idMaterialCookie][2] = $cookie[$idMaterialCookie][1] / 1000;
  582.             $sumaHorneado += $cookie[$idMaterialCookie][1];
  583.         }
  584.         $projectHumidity $project->getHumidity()/100;
  585.         $humedadHorneado $projectHumidity $sumaHorneado / ($projectHumidity);
  586.         $totalHorneado $sumaHorneado $humedadHorneado;
  587.         foreach($cookie as $idMaterialCookie => $materialCookie) {
  588.             $cookie[$idMaterialCookie][3] = $materialCookie[1] / $totalHorneado;
  589.             //$cookie[$idMaterialCookie][3] = $cookie[$idMaterialCookie][1] / $totalHorneado;
  590.             $this->nutricionalCookie->addRawMaterial($MaterialesUsados[$idMaterialCookie], $cookie[$idMaterialCookie][3]);
  591.                 $cookie[$idMaterialCookie][4] = $cookieOriginal[$idMaterialCookie][1] / $totalHorneado;
  592.                 $cookie[$idMaterialCookie][5] = $cookieOriginal[$idMaterialCookie][1];
  593.         }
  594.         $projectCalcs->setIngredientesCookie($cookie);
  595.         /*echo "\n\n== AMASADA TERMINADA ==\n\n";
  596.         echo var_export($cookie, true);
  597.         echo "\n\n";*/
  598.         $perdidaEstimada $pesoAmasada array_reduce($pesoRelacionAmasada, fn($a,$r)=>$a+$r,0) - $totalHorneado;
  599.         if ($pesoAmasada === 0) {
  600.             $perdidaEstimadaPorcentaje $perdidaEstimada;
  601.         }  else {
  602.             $perdidaEstimadaPorcentaje $perdidaEstimada $pesoAmasada;
  603.         }
  604.         $projectCalcs->setTotalPesoCookie(sprintf('%01.4f'$sumaHorneado 1000)); // <- A kg
  605.         $projectCalcs->setHumedadHorneado(sprintf('%01.4f'$humedadHorneado 1000)); // <- A kg
  606.         $projectCalcs->setTotalHorneado(sprintf('%01.4f'$totalHorneado 1000)); // <- A Kg
  607.         $projectCalcs->setPerdidaEstimada(sprintf('%01.4f'$perdidaEstimada 1000)); // <- A kg
  608.         $projectCalcs->setPerdidaEstimadaPorcentaje(sprintf('%01.5f'$perdidaEstimadaPorcentaje));
  609.         /** FIN INGREDIENTES DE LA GALLETA */
  610.         /** INGREDIENTES DESPUES DEL HORNO */
  611.         $afterOvenRecipeCalcs = [];
  612.         $costes['after'] = [];
  613.         $BDIngredientesDespuesHorno = [];
  614.         foreach ($afterOvenTests as $recipeKey => $recipeTest) {
  615.             $nombreTipo $recipeTest->getRecipe()->getType();
  616.             $BDIngredientesDespuesHorno[$nombreTipo] = [];
  617.             $materials $recipeTestRawMaterialRepository->findBy(['recipeTest' => $recipeTest]);
  618.             $recipeId $recipeTest->getRecipe()->getId();
  619.             //$recipeName = $recipeTest->getRecipe()->getType();
  620.             $afterOvenRecipeCalcs[$recipeId] = [];
  621.             $costes['after'][$recipeKey] = [];
  622.             $this->nutricionalDespuesHorno[$recipeKey] = new NutritionalInfo();
  623.             $total 0;
  624.             foreach ($materials as $material) {
  625.                 $rawMaterial $material->getRawMaterial();
  626.                 if (!isset($MaterialesUsados[$rawMaterial->getId()])) {
  627.                     $MaterialesUsados[$rawMaterial->getId()] = $rawMaterial;
  628.                 }
  629.                 $quantity $material->getQuantity();
  630.                 $afterOvenRecipeCalcs[$recipeId][$rawMaterial->getId()] = [$rawMaterial->getName(), $quantity$quantity 10000];
  631.                 $total += $quantity;
  632.             }
  633.             array_walk($afterOvenRecipeCalcs[$recipeId], fn(&$r)=> $r[3] = isset($r[1]) ? ($r[1] / $total) : '');
  634.             foreach ($materials as $material) {
  635.                 $rawMaterial $material->getRawMaterial();
  636.                 $quantity $material->getQuantity();
  637.                 $costes['after'][$recipeKey][$rawMaterial->getId()] = [$rawMaterial->getName(), $quantity $total$rawMaterial->getPrice(), $rawMaterial->getPrice() * ($quantity $total)];
  638.                 $this->nutricionalDespuesHorno[$recipeKey]->addRawMaterialWithoutHumidity($rawMaterial$quantity $total);
  639.             }
  640.             $BDIngredientesDespuesHorno[$recipeKey] = $afterOvenRecipeCalcs[$recipeId];
  641.         }
  642.         /*echo "\n\n== INGREDIENTES DESPUES HORNO ==\n\n";
  643.         var_export($BDIngredientesDespuesHorno);
  644.         echo "\n\n";*/
  645.         $projectCalcs->setIngredientesDespuesHorno($BDIngredientesDespuesHorno);
  646.         unset($BDIngredientesDespuesHorno);
  647.         /** FIN INGREDIENTES DESPUES DEL HORNO */
  648.         /** INGREDIENTES PRODUCTO TERMINADO */
  649.         $productoTerminado = [];
  650.         $cookiePercentage 100 array_reduce($afterOvenBakingPercentage, fn($a,$r)=>$a+$r0);
  651.         //echo "Porcentaje galleta: {$cookiePercentage}\n\n";
  652.         foreach($cookie as $idMaterialCookie => $materialCookie) {
  653.             $productoTerminado[$idMaterialCookie] = [
  654.                 $materialCookie[0],
  655.                 $materialCookie[3] * $cookiePercentage,
  656.                 isset($materialCookie[4]) ? $materialCookie[4] * $cookiePercentage null,
  657.                 $materialCookie[1],
  658.                 $idMaterialCookie
  659.             ];
  660.         }
  661.         //var_dump($this->nutricionalCookie);
  662.         $nutricionalProductoFinal = new NutritionalInfo();
  663.         $nutricionalProductoFinal->addSimple($this->nutricionalCookie$cookiePercentage 100);
  664.         foreach ($afterOvenTests as $recipeKey => $recipeTest) {
  665.             $nutricionalProductoFinal->addSimple($this->nutricionalDespuesHorno[$recipeKey], $recipeTest->getRecipe()->getBaking() / 100);
  666.         }
  667.         //var_dump($this->nutricionalProductoFinal);
  668.         $key 0;
  669.         foreach ($afterOvenRecipeCalcs as $recipe) {
  670.             foreach ($recipe as $materialId => $materialInfo) {
  671.                 if (!isset($productoTerminado[$materialId])) {
  672.                     $productoTerminado[$materialId] = [
  673.                         $materialInfo[0],
  674.                         $materialInfo[3] * $afterOvenBakingPercentage[$key],
  675.                         $materialInfo[3] * $afterOvenBakingPercentage[$key],
  676.                         $materialInfo[1],
  677.                         $materialId,
  678.                     ];
  679.                 } else {
  680.                     $productoTerminado[$materialId][1] += $materialInfo[3] * $afterOvenBakingPercentage[$key];
  681.                     $productoTerminado[$materialId][2] += $materialInfo[3] * $afterOvenBakingPercentage[$key];
  682.                 }
  683.             }
  684.             $key++;
  685.         }
  686.         $projectCalcs->setHumedadGalleta(sprintf('%01.4f'$projectHumidity $cookiePercentage));
  687.         /*foreach ($productoTerminado as $materialId => $lineaMaterial) {
  688.             echo "Añadir material {$MaterialesUsados[$materialId]->getName()} {$MaterialesUsados[$materialId]->getGrease()} {$lineaMaterial[1]}\n";
  689.             //$this->nutricionalProductoFinal->addRawMaterialWithHumidity($MaterialesUsados[$materialId], $lineaMaterial[1] / 100);
  690.         }*/
  691.         $projectCalcs->setIngredientesProductoTerminado($productoTerminado);
  692.         /*echo "\n\n== INGREDIENTES PRODUCTO TERMINADO ==\n\n";
  693.         var_export($productoTerminado);
  694.         echo "\n\n";*/
  695.         /** FIN INGREDIENTES PRODUCTO TERMINADO */
  696.         /** COSTES AMASADA */
  697.         $recipeTotalCost array_reduce($costes['before']['amasada'], fn($a,$r) => $a $r[3], 0);
  698.         $recipeKneadingCost $recipeTotalCost $J17;
  699.         //$projectCalcs->setCosteAmasada(sprintf('%01.4f', $recipeTotalCost));
  700.         $projectCalcs->setCostesAmasada($costes['before']['amasada']);
  701.         /** FIN COSTES AMASADA */
  702.         /** COSTES ANTES HORNO */
  703.         $key 0;
  704.         $BDCostesAntesHorno = [];
  705.         foreach ($costes['before']['others'] as $recipeType => $recipeCosts) {
  706.             $recipeTotalCosts array_reduce($recipeCosts, fn($a,$r) => $a $r[3], 0);
  707.             $BDCostesAntesHorno[$recipeType] = $recipeTotalCosts;
  708.             $recipeKneadingCost += $recipeTotalCosts $porcentajesRecetas[$key];
  709.             $key++;
  710.         }
  711.         $projectCalcs->setCostesAntesHorno($BDCostesAntesHorno);
  712.         //$projectCalcs->setCosteAmasada(sprintf('%01.4f', $recipeKneadingCost));
  713.         unset($BDCostesAntesHorno);
  714.         /** FIN COSTES ANTES HORNO */
  715.         $totalKneadingCost $recipeKneadingCost * ($pesoAmasada array_reduce($pesoRelacionAmasada, fn($a,$k)=>$a $k0)) / $totalHorneado;
  716.         $totalProductCost $totalKneadingCost * ($cookiePercentage 100);
  717.         $projectCalcs->setCosteAmasada(sprintf('%01.4f'$totalKneadingCost));
  718.         /** COSTES DESPUES HORNO */
  719.         $key 0;
  720.         $BDCostesDespuesHorno = []; //var_dump($costes['after']);
  721.         foreach ($costes['after'] as $recipeKey => $recipeCosts) {
  722.             $recipeTotalCosts array_reduce($recipeCosts, fn($a,$r) => $a $r[3], 0);
  723.             $totalProductCost += $recipeTotalCosts * ($afterOvenBakingPercentage[$key] / 100);
  724.             $BDCostesDespuesHorno[$recipeKey] = $recipeCosts;
  725.             $key++;
  726.         }
  727.         $projectCalcs->setCostesDespuesHorno($BDCostesDespuesHorno);
  728.         unset($BDCostesDespuesHorno);
  729.         /** FIN COSTES DESPUES HORNO */
  730.         $projectCalcs->setCosteProductoTerminado(sprintf('%01.4f',$totalProductCost));
  731.         $projectCalcs
  732.             ->setInformacionNutricionalCookie($this->nutricionalCookie->result())
  733.             ->setCdrCookie($this->nutricionalCookie->cdr())
  734.             ->setNutriscoreCookie($this->nutricionalCookie->nutriscore($entityManager));
  735.         /*$nutricionalDespues = [];
  736.         $cdrDespues = [];
  737.         $nutriscoreDespues = [];
  738.         foreach ($this->nutricionalDespuesHorno as $tipo => $nutricional) {
  739.             $nutricionalDespues[$tipo] = $nutricional->result();
  740.             $cdrDespues[$tipo] = $nutricional->cdr();
  741.             $nutriscoreDespues[$tipo] = $nutricional->nutriscore($entityManager);
  742.         }
  743.         $projectCalcs
  744.             ->setInformacionNutricionalDespuesHorno($nutricionalDespues)
  745.             ->setCdrDespuesHorno($cdrDespues)
  746.             ->setNutriscoreDespuesHorno($nutriscoreDespues);
  747.         unset($nutricionalDespues);
  748.         unset($cdrDespues);
  749.         unset($nutriscoreDespues);*/
  750.         //var_dump($this->nutricionalProductoFinal->result());
  751.         $projectCalcs->setInformacionNutricionalProducto($nutricionalProductoFinal->result());
  752.         //$projectCalcs->setInformacionNutricionalProductoAjustado($this->nutricionalProductoFinal->result());
  753.         $projectCalcs->setCdrProducto($nutricionalProductoFinal->cdr());
  754.         $nutriscoreFinal $nutricionalProductoFinal->nutriscore($entityManager);
  755.         $projectCalcs->setNutriscoreProducto($nutriscoreFinal);
  756.         $projectCalcs->setNutriscoreProductoValor(array_values(array_filter($nutriscoreFinal, fn($r) => $r['key'] === 'Nutriscore'))[0]['value']);
  757.         $projectCalcs->setNutriscoreProductoLetra(array_values(array_filter($nutriscoreFinal, fn($r) => $r['key'] === 'Nutriscore_letter'))[0]['value']);
  758.         $entityManager->persist($projectCalcs);
  759.         $entityManager->persist($project);
  760.         $entityManager->flush();
  761.         return new JsonResponse([
  762.             'nutriscore' => $nutriscoreFinal,
  763.             //'j' => $this->nutricionalProductoFinal->result(),
  764.             'id_calculo' => $projectCalcs->getId(),
  765.         ]);
  766.     }
  767. }