<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Psr\Log\LoggerInterface;
use App\Entity\Okpd;
class AppController extends AbstractController
{
/*
* Страница с формой
*/
public function index(): Response
{
if (!$this->isAlarmMode()) return $this->redirect($this->getParameter('app.fgis_url'));
return $this->render('app/index.html.twig');
}
/*
* Поиск ОКПД
*/
public function getOkpd(ManagerRegistry $doctrine, Request $request): JsonResponse
{
if (!$this->isAlarmMode()) return $this->redirect($this->getParameter('app.fgis_url'));
$query = $request->get('q');
$type = (int)$request->get('t');
$okpds = $doctrine->getManager()->getRepository(Okpd::class)->searchOkpd($query, $type);
return new JsonResponse(['results' => $okpds]);
}
/*
* Получаем список свойств
*/
public function getAttributes(ManagerRegistry $doctrine, Request $request): JsonResponse
{
if (!$this->isAlarmMode()) return $this->redirect($this->getParameter('app.fgis_url'));
$em = $doctrine->getManager();
try {
$okpd = $request->get('okpd');
if (!$okpd) throw new \Exception('Ошибка! Не указан код ОКПД2.');
$direction = (int)$request->get('direction');
if (!$direction) throw new \Exception('Ошибка! Не указан вид использования.');
$country = $request->get('country');
if ($direction === 3 && !$country) throw new \Exception('Ошибка! Не указана страна назначения.');
$attributes = $em->getRepository(Okpd::class)->getAttributes($okpd, $direction, $country);
$response = [
'success' => true,
'attributes' => $attributes
];
} catch (\Exception $ex) {
$response = [
'success' => false,
'message' => $ex->getMessage()
];
}
return new JsonResponse($response);
}
/*
* Генерим номера документов
*/
public function generateNumbers($packType, ManagerRegistry $doctrine, Request $request, LoggerInterface $logger, MailerInterface $mailer): JsonResponse
{
if (!$this->isAlarmMode()) return $this->redirect($this->getParameter('app.fgis_url'));
$em = $doctrine->getManager();
$inn = $request->get('fieldInn');
$kpp = $request->get('fieldKpp');
$mailto = $request->get('fieldEmail');
try {
$data = $em->getRepository(Okpd::class)->processSubmit($request, $packType);
if (!$data || !is_array($data) || !is_array($data['partnumbers']) || !is_array($data['sdiznumbers'])) throw new \Exception('Ошибка при генерации номеров документов.');
$file = 'https://' . $request->getHost() . '/download/' . $inn . '/' . $data['id'];
$logger->info('Документы успешно созданы', [
'ip' => $request->getClientIp(),
'inn' => $inn,
'packtype' => $packType,
'packid' => $data['id']
]);
$email = (new TemplatedEmail())
->from('Аварийная форма Зерно <alarm@specagro.ru>')
->to($mailto)
->subject('ФГИС Зерно. Номера ' . ($packType === 'parts' ? 'партий' : ($packType === 'sdiz' ? 'СДИЗ' : 'партий и СДИЗ')))
->htmlTemplate('emails/pack.html.twig')
->context([
'file' => $file,
'partnumbers' => $data['partnumbers'],
'sdiznumbers' => $data['sdiznumbers'],
'inn' => $inn,
'kpp' => $kpp,
'okpd' => $data['okpd'],
'date' => $data['date']
]);
$mailer->send($email);
$response = [
'success' => true,
'file' => $file
];
} catch (\Throwable $ex) {
if (get_class($ex) === 'Doctrine\DBAL\Exception' || is_subclass_of($ex, 'Doctrine\DBAL\Exception')) {
$message = "Ошибка при работе с БД. Попробуйте позже.";
} else {
$message = $ex->getMessage();
}
$logger->critical('Ошибка при генерации документов', [
'ip' => $request->getClientIp(),
'inn' => $inn,
'error' => $ex->getMessage()
]);
$response = [
'success' => false,
'message' => $message
];
}
return new JsonResponse($response);
}
/*
* Скачиваем документы
*/
public function downloadDocuments($inn, $packId, ManagerRegistry $doctrine): BinaryFileResponse
{
//if (!$this->isAlarmMode()) return $this->redirect($this->getParameter('app.fgis_url'));
$em = $doctrine->getManager();
$packInfo = $em->getRepository(Okpd::class)->getPack($inn, $packId);
if (!$packInfo) throw $this->createNotFoundException();
$cacheDir = $this->getParameter('kernel.cache_dir') . '/../packs/';
$tempDir = $this->getParameter('kernel.cache_dir') . '/../temp/' . $inn . '-' . $packId;
$filename = $packId . '.zip';
$cachedFile = $cacheDir . $inn . '-' . $filename;
$parts = null;
$sdiz = null;
// Сначала ищем в кэше
if (file_exists($cachedFile)) { // Если найден, то просто отдаем, ничего не делаем
} else { // Если не найден, то генерим
mkdir($tempDir);
// Собираем номера
if ($packInfo['packtype'] === 'parts' || $packInfo['packtype'] === 'all') {
$parts = $em->getRepository(Okpd::class)->getParts($packInfo['inn'], $packInfo['packid']);
if (count($parts) === 0) $parts = null;
}
if ($packInfo['packtype'] === 'sdiz' || $packInfo['packtype'] === 'all') {
$sdiz = $em->getRepository(Okpd::class)->getSdiz($packInfo['inn'], $packInfo['packid']);
if (count($sdiz) === 0) $sdiz = null;
}
$em->getRepository(Okpd::class)->generateNumbersFile($tempDir, $packInfo, $parts, $sdiz); // Генерим файл с номерами и свойствами
if ($packInfo['packtype'] === 'sdiz' || $packInfo['packtype'] === 'all') { // Генерим файлы СДИЗов
$em->getRepository(Okpd::class)->generateSdizFiles($tempDir, $packInfo, $sdiz, $parts);
}
$zip = new \ZipArchive();
$zip->open($cachedFile, \ZipArchive::CREATE);
$zip->addGlob($tempDir . '/*.{xlsx}', GLOB_BRACE, ['remove_all_path' => TRUE]);
$zip->close();
$this->removeDirectory($tempDir);
}
$response = new BinaryFileResponse($cachedFile);
$response->headers->set('Content-Type', 'application/zip');
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename);
return $response;
}
private function removeDirectory($dir)
{
if ($objs = glob($dir . "/*")) {
foreach($objs as $obj) {
is_dir($obj) ? removeDirectory($obj) : unlink($obj);
}
}
rmdir($dir);
}
private function isAlarmMode()
{
return strtolower($this->getParameter('app.alarm_mode')) === 'true';
}
}