<?php
namespace App\Controller;
use App\Entity\IndentRequest;
use App\Form\IndentRequestType;
use App\Repository\CaseRepository;
use App\Repository\IndentRequestRepository;
use App\Service\Pagination;
use Doctrine\ORM\EntityManagerInterface;
use PhpOffice\PhpSpreadsheet\{IOFactory, Spreadsheet, Style\Alignment};
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\{Request, Response, ResponseHeaderBag};
use Symfony\Component\Routing\Annotation\Route;
use Nzo\UrlEncryptorBundle\Annotations\ParamDecryptor;
#[Route(path: '/indents')]
#[Security("is_granted('ROLE_PHARMA') or is_granted('ROLE_LAB_TECH') or is_granted('ROLE_WARD') or is_granted('ROLE_STOCK') or is_granted('ROLE_RAD') or is_granted('ROLE_DENT_WARD')")]
class IndentRequestController extends AbstractController
{
#[Route(path: '/', name: 'indent_request_index', methods: ['GET'])]
public function index(Request $request, Pagination $pagination, CaseRepository $caseRepo, IndentRequestRepository $irRepo): Response
{
$indents = $pagination->paginate($this->getIndentRequestQuery($request, $irRepo), $request, $this->getParameter('items_per_page'));
return $this->render('indent_request/index.html.twig', [
'indents' => $indents,
'drugs' => $caseRepo->getEssentialDrugs($this->getUser()->getHospital()->getType()),
'last_page' => $pagination->lastPage($indents),
'url' => 'indent_request_index'
]);
}
#[Route(path: '/export', name: 'indent_request_export', methods: ['GET'])]
public function export(Request $request, IndentRequestRepository $irRepo): Response
{
$indents = $this->getIndentRequestQuery($request, $irRepo)->getResult();
$spreadsheet = new Spreadsheet();
$spreadsheet->setActiveSheetIndex(0)
->setCellValue('A1', 'Indent Requests')
->mergeCells('A1:N1')
->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
$spreadsheet->getActiveSheet()
->setCellValue('A3', 'Indent No.')
->setCellValue('B3', 'Stock Center')
->setCellValue('C3', 'Major Demand Category')
->setCellValue('D3', 'Sub-category')
->setCellValue('E3', 'Group')
->setCellValue('F3', 'Sub-group')
->setCellValue('G3', 'Item')
->setCellValue('H3', 'Drug Type')
->setCellValue('I3', 'Strength')
->setCellValue('J3', 'Basic Unit')
->setCellValue('K3', 'Unit Pack')
->setCellValue('L3', 'Description')
->setCellValue('M3', 'Demand in Unit Pack')
->setCellValue('N3', 'Status');
$i = 4;
if ($indents) {
foreach ($indents as $indent) {
if ($indent->getItemOther()) {
$itemType = $indent->getItemOther();
} elseif ($indent->getLabMaterial()) {
$itemType = $indent->getLabMaterial();
} elseif ($indent->getEssentialEquipment()) {
$itemType = $indent->getEssentialEquipment();
} elseif ($indent->getDrug()) {
$itemType = $indent->getDrug();
} else {
$itemType = '-';
}
$spreadsheet->getActiveSheet()
->setCellValue('A' . $i, $indent->getIndentNum())
->setCellValue('B' . $i, $indent->getSource())
->setCellValue('C' . $i, $indent->getDemandCategory())
->setCellValue('D' . $i, $indent->getDemandSubCategory())
->setCellValue('E' . $i, $indent->getGroupName())
->setCellValue('F' . $i, $indent->getSubGroupName())
->setCellValue('G' . $i, $itemType)
->setCellValue('H' . $i, $indent->getDrugType() ?: '-')
->setCellValue('I' . $i, $indent->getStrength() ?: '-')
->setCellValue('J' . $i, $indent->getBasicUnit() ?: '-')
->setCellValue('K' . $i, $indent->getUnitPack() ?: '-')
->setCellValue('L' . $i, $indent->getDescription())
->setCellValue('M' . $i, $indent->getRecdDemandUnitPack() ?: '-')
->setCellValue('N' . $i, $indent->getStatus() == 'Partial' ? 'Partially Accepted' : $indent->getStatus());
$i++;
}
} else {
$spreadsheet->getActiveSheet()
->setCellValue('A4', 'No records found.')
->mergeCells('A4:N4')
->getStyle('A4')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
}
$fileName = 'indent-requests-' . date('d-m-Y') . '.xlsx';
$tempFile = tempnam(sys_get_temp_dir(), $fileName);
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save($tempFile);
return $this->file($tempFile, $fileName, ResponseHeaderBag::DISPOSITION_INLINE);
}
#[Route(path: '/new', name: 'indent_request_new', methods: ['GET', 'POST'])]
public function new(Request $request, EntityManagerInterface $entityManager): Response
{
$indentRequest = new IndentRequest();
$indentRequest
->setHospital($this->getUser()->getHospital())
->setDepartment($this->getDepartment());
$form = $this->createForm(IndentRequestType::class, $indentRequest);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($indentRequest);
$entityManager->flush();
$indentRequest->setIndentNum('IND-' . date('Y') . '-' . sprintf('%07d', $indentRequest->getId()));
$entityManager->persist($indentRequest);
$entityManager->flush();
$this->addFlash(
'success',
'New indent request generated successfully!'
);
return $this->redirectToRoute('indent_request_index');
}
return $this->renderForm('indent_request/new.html.twig', [
'indent_request' => $indentRequest,
'form' => $form
]);
}
#[Route(path: '/view/{id}', name: 'indent_request_show', methods: ['GET'])]
#[ParamDecryptor(["id"])]
public function show(IndentRequest $indentRequest): Response
{
return $this->render('indent_request/show.html.twig', [
'indent' => $indentRequest
]);
}
private function getDepartment()
{
return match (true) {
$this->isGranted('ROLE_PHARMA') ||
$this->isGranted('ROLE_DOC') ||
$this->isGranted('ROLE_HOSP_ADMIN') ||
$this->isGranted('ROLE_DENT') => 'Pharmacy',
$this->isGranted('ROLE_LAB_TECH') => 'Laboratory',
$this->isGranted('ROLE_RAD') => 'Radiology',
default => 'Ward'
};
}
private function getIndentRequestQuery(Request $request, IndentRequestRepository $irRepo)
{
/** @var User user entity */
$user = $this->getUser();
$qb = $irRepo->createQueryBuilder('id')
->where('id.hospital = :hospital')
->setParameter('hospital', $user->getHospital())
->orderBy('id.createdAt', 'DESC');
if (!$this->isGranted('ROLE_STOCK')) {
$qb
->andWhere('id.createdBy = :user')
->setParameter(':user', $user);
}
if ($request->get('drug')) {
$qb
->leftJoin('id.drug', 'd')
->andWhere('d.id = :id')
->setParameter('id', $request->get('drug'));
}
if ($request->get('range')) {
[$from, $to] = explode(' / ', $request->get('range'));
if ($from && $to) {
$qb
->andWhere('id.updatedAt BETWEEN :from AND :to')
->setParameter('from', $from)
->setParameter('to', $to);
}
}
return $qb->getQuery();
}
}