<?php
namespace App\Controller\Manager;
use App\Entity\Paper;
use App\Entity\PaperStock;
use App\Services\ForecastingManager;
use App\Form\Manager\StockCustomerEditType;
use App\Form\Manager\StockEditType;
use App\Form\Manager\StockProviderEditType;
use Doctrine\ORM\EntityManagerInterface;
use App\Repository\PaperStockGroupRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\Repository\CustomerOrderItemRepository;
use App\Repository\PaperRepository;
use App\Repository\ProviderOrderItemRepository;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
#[Route(name: 'stock_')]
class ForecastingController extends AbstractController
{
protected $forecastingManager;
public function __construct(ForecastingManager $forecastingManager)
{
$this->forecastingManager = $forecastingManager;
}
#[Route('/manager/stocks/forecasting/outofstocks')]
public function outOfStocks(PaperRepository $paperRepository, Request $request, EntityManagerInterface $em): Response
{
// Retrieve filters
$filters = $this->getFilters($request);
$papers = $paperRepository->findAll();
foreach ($papers as $paper) {
$lastQuantity = $paper->getQuantity();
$stockOrders = $this->forecastingManager->getStockOrders($paper, $lastQuantity, $filters);
$this->forecastingManager->updateOutOfStocks($paper, $stockOrders);
}
$em->flush();
return $this->json('ok');
}
#[Route('/manager/stocks/{id}/forecasting/forecasting', name: 'forecasting', methods: ['GET', 'POST'])]
public function forecasting(Paper $paper, Request $request): Response
{
// Retrieve filters
$filters = $this->getFilters($request);
// Retrieve stocks
$stocks = $this->forecastingManager->getStocks($paper, $filters);
$lastQuantity = count($stocks) ? $stocks[count($stocks) - 1]->getQuantity() : $paper->getQuantity();
// Retrieve and merge customer and provider orders
$stockOrders = $this->forecastingManager->getStockOrders($paper, $lastQuantity, $filters);
return $this->renderForm('manager/stock/forecasting/forecasting.html.twig', [
'paper' => $paper,
'stocks' => $stocks,
'stockOrders' => $stockOrders,
'hide_today' => $filters['to'] && new \DateTimeImmutable($filters['to']) < (new \DateTimeImmutable())->setTime(0, 0, 0)
]);
}
#[Route('/manager/stocks/{id}/forecasting-ajax', name: 'forecasting_ajax')]
public function forecastingAjax(Paper $paper, Request $request)
{
// Retrieve filters
$filters = $this->getFilters($request);
// retrieve forecasting
$response = $this->getForecastingAjax($paper, $filters);
return $this->json($response);
}
#[Route('/manager/stocks/forecasting-ajax-multiple', name: 'forecasting_ajax_multiple')]
public function forecastingAjaxMultiple(PaperRepository $paperRepository, Request $request)
{
if (!$request->request->has('ids')) throw $this->createNotFoundException();
// Retrieve filters
$filters = $this->getFilters($request);
// Get papers
$ids = $request->request->all()['ids'];
$papers = $paperRepository->findBy(['id' => $ids]);
// Merge templates
$response = '';
foreach ($papers as $paper) {
$template = $this->getForecastingAjax($paper, $filters);
$response .= '<table data-forecasting-id="' . $paper->getId() . '">' . $template . '</table>';
}
return $this->json($response);
}
#[Route('/manager/stocks/{id}/forecasting/edit', name: 'forecasting_edit', methods: ['POST'])]
public function forecastingEdit(Paper $paper, Request $request, CustomerOrderItemRepository $customerOrderItemRepository, ProviderOrderItemRepository $providerOrderItemRepository, PaperStockGroupRepository $paperStockGroupRepository, EntityManagerInterface $em): Response
{
if (!$request->request->has('stock') || !$request->request->has('type')) throw $this->createNotFoundException();
// Select repository and form type from stock type
switch ($request->request->get('type')) {
case PaperStock::TYPE_ORDER_CUSTOMER :
$repository = $customerOrderItemRepository;
$formType = StockCustomerEditType::class;
break;
case PaperStock::TYPE_ORDER_PROVIDER :
$repository = $providerOrderItemRepository;
$formType = StockProviderEditType::class;
break;
default :
$repository = $paperStockGroupRepository;
$formType = StockEditType::class;
}
$stock = $repository->find($request->request->get('stock'));
if(null == $stock) throw $this->createNotFoundException();
$form = $this->createForm($formType, $stock);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
// Set date edited if date is different from order's date
switch ($request->request->get('type')) {
case PaperStock::TYPE_ORDER_CUSTOMER :
$stock->setProductionEdited( $stock->getProductionAt() != $stock->getCustomerOrder()->getDeliveredAt() );
break;
case PaperStock::TYPE_ORDER_PROVIDER :
$stock->setDeliveryEdited( $stock->getDeliveredAt() != $stock->getProviderOrder()->getDeliveredEstimationAt() );
break;
}
$em->flush();
return $this->json([]);
}
$statusCode = 422;
}
$response = $this->renderView('manager/stock/forecasting/_forecasting_edit_form.html.twig', [
'form' => $form->createView()
]);
return $this->json($response, isset($statusCode) ? $statusCode : 200);
}
private function getForecastingAjax(Paper $paper, array $filters): string
{
$lastQuantity = $paper->getQuantity();
// Retrieve and merge customer and provider orders
$stockOrders = $this->forecastingManager->getStockOrders($paper, $lastQuantity, $filters);
$template = $this->renderView('manager/stock/forecasting/_forecasting-tbody.html.twig', [
'paper' => $paper,
'stockOrders' => $stockOrders,
'hide_today' => true
]);
return $template;
}
private function getFilters(Request $request): array
{
$filters = [
'archived' => false,
'from' => null,
'to' => null
];
if ($request->query->has('filter')) {
foreach ($request->query->all()['filter'] as $field => $filter) {
if (!isset($filter['value']) || $filter['value'] == "" || !isset($filter['comparator'])) continue;
switch ($field) {
case 'from' :
$filters['from'] = $filter['value'];
break;
case 'to' :
$filters['to'] = $filter['value'];
break;
case 'archived' :
if ($filter['value'] == "1") $filters['archived'] = true;
break;
}
}
}
return $filters;
}
}