more bug fix in print doc and pdf generator

This commit is contained in:
Hesabix 2025-03-09 18:46:38 +00:00
parent c3fbaa1d53
commit 2ff6c04b26
3 changed files with 284 additions and 60 deletions

View file

@ -3,39 +3,34 @@
namespace App\Controller;
use App\Entity\ChangeReport;
use App\Entity\HesabdariDoc;
use App\Entity\Statment;
use App\Entity\User;
use App\Service\Access;
use App\Entity\PrinterQueue;
use App\Service\Jdate;
use App\Service\PdfMGR;
use App\Service\Provider;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Entity\Business;
use App\Entity\PrinterQueue;
use App\Service\pdfMGR;
use App\Service\Provider;
class GeneralController extends AbstractController
{
#[Route('/api/general/stat', name: 'general_stat')]
public function general_stat(EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
{
//get last version number
$version = '0.0.1';
$lastUpdateDate = '1399';
$lastUpdateDes = '';
$last = $entityManager->getRepository(ChangeReport::class)->findOneBy([], ['id' => 'DESC']);
if ($last) {
$version = $last->getVersion();
$lastUpdateDate = $jdate->jdate('Y/n/d', $last->getDateSubmit());
$lastUpdateDes = $last->getBody();
}
return $this->json([
'version' => $version,
'lastUpdateDate' => $lastUpdateDate,
@ -44,7 +39,7 @@ class GeneralController extends AbstractController
}
#[Route('/api/general/statements', name: 'general_statement')]
public function general_statement(EntityManagerInterface $entityManager, Jdate $jdate): JsonResponse
public function general_statement(EntityManagerInterface $entityManager): JsonResponse
{
return $this->json($entityManager->getRepository(Statment::class)->findBy([], ['id' => 'DESC']));
}
@ -52,26 +47,30 @@ class GeneralController extends AbstractController
#[Route('/api/general/get/time', name: 'general_get_time')]
public function general_get_time(Jdate $jdate, Request $request): JsonResponse
{
$params = [];
if ($content = $request->getContent()) {
$params = json_decode($content, true);
}
if (array_key_exists('format', $params))
return $this->json(['timeNow' => $jdate->jdate($params['format'], time()), 'ts' => time()]);
return $this->json(['timeNow' => $jdate->jdate('Y/n/d', time()), 'ts' => time()]);
$params = json_decode($request->getContent(), true) ?? [];
$format = $params['format'] ?? 'Y/n/d';
return $this->json(['timeNow' => $jdate->jdate($format, time()), 'ts' => time()]);
}
#[Route('/front/print/{id}', name: 'app_front_print')]
public function app_front_print(Provider $provider, EntityManagerInterface $entityManager, pdfMGR $pdfMGR, string $id)
public function app_front_print(Provider $provider, EntityManagerInterface $entityManager, PdfMGR $pdfMGR, string $id): Response
{
$print = $entityManager->getRepository(PrinterQueue::class)->findOneBy(['pid' => $id]);
if (!$print)
throw $this->createNotFoundException();
if (!$print) {
return new JsonResponse(['error' => 'Print job not found'], Response::HTTP_NOT_FOUND);
}
if (empty($print->getView())) {
return new JsonResponse(['error' => 'Empty print content'], Response::HTTP_BAD_REQUEST);
}
if ($print->isPosprint()) {
$pdfMGR->streamTwig2PDFInvoiceType($print);
} else {
$pdfMGR->streamTwig2PDF($print);
}
return new Response('');
return new Response('Print job completed', Response::HTTP_OK);
}
}

View file

@ -0,0 +1,202 @@
<?php
namespace App\Controller;
use App\Entity\HesabdariDoc;
use App\Entity\HesabdariRow;
use App\Entity\HesabdariTable;
use App\Service\Access;
use App\Service\Extractor;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/api')]
class HesabdariDocController extends AbstractController
{
private $em;
private $access;
private $extractor;
public function __construct(EntityManagerInterface $em, Access $access, Extractor $extractor)
{
$this->em = $em;
$this->access = $access;
$this->extractor = $extractor;
}
#[Route('/hesabdari/tables', name: 'get_hesabdari_tables', methods: ['GET'])]
public function getHesabdariTables(): JsonResponse
{
$accessData = $this->access->hasRole('accounting');
if (!$accessData) {
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
}
$bid = $accessData['bid'];
// گرفتن همه حساب‌ها (عمومی و خصوصی)
$tables = $this->em->getRepository(HesabdariTable::class)->findBy([
'bid' => [$bid, null], // حساب‌های عمومی (null) و خصوصی (bid)
]);
// تبدیل به ساختار درختی
$tree = $this->buildTree($tables);
return new JsonResponse($this->extractor->operationSuccess($tree, 'لیست حساب‌ها با موفقیت دریافت شد'));
}
private function buildTree(array $tables): array
{
$tree = [];
$map = [];
// مپ کردن همه حساب‌ها
foreach ($tables as $table) {
$map[$table->getId()] = [
'id' => $table->getId(),
'name' => $table->getName(),
'code' => $table->getCode(),
'type' => $table->getType(),
'bid' => $table->getBid(),
'children' => [],
];
}
// ساخت درخت
foreach ($tables as $table) {
$node = &$map[$table->getId()];
$upper = $table->getUpper(); // این یه شیء HesabdariTable یا null هست
$upperId = $upper ? $upper->getId() : null; // اگه upper باشه، idش رو بگیریم
// اگه upper برابر null یا 0 باشه، ریشه‌ست
if ($upperId === null || $upperId === 0) {
$tree[] = &$node;
} elseif (isset($map[$upperId])) {
$map[$upperId]['children'][] = &$node;
}
}
return $tree;
}
#[Route('/hesabdari/doc', name: 'create_hesabdari_doc', methods: ['POST'])]
public function create(Request $request): JsonResponse
{
$accessData = $this->access->hasRole('accounting');
if (!$accessData) {
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
}
$data = json_decode($request->getContent(), true);
if (!$data || !isset($data['date']) || !isset($data['rows'])) {
return new JsonResponse($this->extractor->paramsNotSend(), 400);
}
$doc = new HesabdariDoc();
$doc->setBid($accessData['bid']);
$doc->setSubmitter($accessData['user']);
$doc->setYear($accessData['year']);
$doc->setMoney($accessData['money']);
$doc->setDate($data['date']);
$doc->setDateSubmit((string) time());
$doc->setType('doc');
$doc->setCode($this->generateDocCode($accessData['bid']));
$totalBd = 0;
$totalBs = 0;
foreach ($data['rows'] as $rowData) {
$row = new HesabdariRow();
$row->setDoc($doc);
$row->setRef($this->em->getRepository('App\Entity\HesabdariTable')->find($rowData['ref']));
$row->setBd($rowData['bd'] ?? '0');
$row->setBs($rowData['bs'] ?? '0');
$row->setDes($rowData['des'] ?? null);
$row->setBid($accessData['bid']);
$row->setYear($accessData['year']);
$totalBd += (int) $row->getBd();
$totalBs += (int) $row->getBs();
$this->em->persist($row);
$doc->addHesabdariRow($row);
}
if ($totalBd !== $totalBs) {
return new JsonResponse($this->extractor->operationFail('جمع بدهکار و بستانکار باید برابر باشد'), 400);
}
$doc->setAmount($totalBd);
$this->em->persist($doc);
$this->em->flush();
return new JsonResponse($this->extractor->operationSuccess(['id' => $doc->getId()], 'سند با موفقیت ثبت شد'));
}
#[Route('/hesabdari/doc/{id}', name: 'edit_hesabdari_doc', methods: ['PUT'])]
public function edit(int $id, Request $request): JsonResponse
{
$accessData = $this->access->hasRole('accounting');
if (!$accessData) {
return new JsonResponse($this->extractor->operationFail('دسترسی ندارید'), 403);
}
$doc = $this->em->getRepository(HesabdariDoc::class)->find($id);
if (!$doc || $doc->getBid() !== $accessData['bid']) {
return new JsonResponse($this->extractor->notFound(), 404);
}
$data = json_decode($request->getContent(), true);
if (!$data || !isset($data['date']) || !isset($data['rows'])) {
return new JsonResponse($this->extractor->paramsNotSend(), 400);
}
$doc->setDate($data['date']);
foreach ($doc->getHesabdariRows() as $row) {
$this->em->remove($row);
}
$doc->getHesabdariRows()->clear();
$totalBd = 0;
$totalBs = 0;
foreach ($data['rows'] as $rowData) {
$row = new HesabdariRow();
$row->setDoc($doc);
$row->setRef($this->em->getRepository('App\Entity\HesabdariTable')->find($rowData['ref']));
$row->setBd($rowData['bd'] ?? '0');
$row->setBs($rowData['bs'] ?? '0');
$row->setDes($rowData['des'] ?? null);
$row->setBid($accessData['bid']);
$row->setYear($accessData['year']);
$totalBd += (int) $row->getBd();
$totalBs += (int) $row->getBs();
$this->em->persist($row);
$doc->addHesabdariRow($row);
}
if ($totalBd !== $totalBs) {
return new JsonResponse($this->extractor->operationFail('جمع بدهکار و بستانکار باید برابر باشد'), 400);
}
$doc->setAmount($totalBd);
$this->em->persist($doc);
$this->em->flush();
return new JsonResponse($this->extractor->operationSuccess(['id' => $doc->getId()], 'سند با موفقیت ویرایش شد'));
}
private function generateDocCode($business): string
{
$lastDoc = $this->em->getRepository(HesabdariDoc::class)->findOneBy(
['bid' => $business],
['code' => 'DESC']
);
$newCode = $lastDoc ? ((int) $lastDoc->getCode() + 1) : 1;
return (string) $newCode;
}
}

View file

@ -3,39 +3,43 @@
namespace App\Service;
use App\Entity\PrinterQueue;
use App\Service\Twig;
use Twig\Environment;
class pdfMGR
{
use Mpdf\Mpdf;
use Mpdf\Config\ConfigVariables;
use Mpdf\Config\FontVariables;
class PdfMGR
{
private $twig;
public function __construct(Twig $twig)
public function __construct(Environment $twig)
{
$this->twig = $twig;
}
public function streamTwig2PDF(PrinterQueue $printQueue,$configs = []){
public function streamTwig2PDF(PrinterQueue $printQueue, $configs = [])
{
// Load Twig File
$template = $this->twig->load('pdf/footer.html.twig');
$footer = $template->render([]);
// Render HTML
$footer = $template->render([
]);
$size = $printQueue->getPaperSize();
if(!$size){ $size = 'A4-L'; }
$defaultConfig = (new \Mpdf\Config\ConfigVariables())->getDefaults();
$size = $printQueue->getPaperSize() ?: 'A4-L';
$defaultConfig = (new ConfigVariables())->getDefaults();
$fontDirs = $defaultConfig['fontDir'];
$defaultFontConfig = (new \Mpdf\Config\FontVariables())->getDefaults();
$defaultFontConfig = (new FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
$mpdf = new \Mpdf\Mpdf([
'mode' => 'utf-8', 'format' => $size,
'fontDir' => array_merge($fontDirs, [
dirname(__DIR__) . '/Fonts',
]),
$tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mpdf';
if (!is_dir($tempDir)) {
mkdir($tempDir, 0777, true);
}
$mpdf = new Mpdf([
'mode' => 'utf-8',
'format' => $size,
'fontDir' => array_merge($fontDirs, [dirname(__DIR__) . '/Fonts']),
'fontdata' => $fontData + [
'vazirmatn' => [
'R' => 'Vazir-Regular-FD.ttf',
@ -45,14 +49,16 @@ class pdfMGR
]
],
'default_font' => 'vazirmatn',
'tempDir' => sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mpdf',
'tempDir' => $tempDir,
'autoArabic' => true,
]);
if($printQueue->isFooter()){
if ($printQueue->isFooter()) {
$mpdf->SetHTMLFooter($footer);
}
$mpdf->WriteHTML($printQueue->getView());
$htmlContent = $printQueue->getView() ?: '<p>محتوای PDF در دسترس نیست.</p>';
$mpdf->WriteHTML($htmlContent);
$mpdf->SetAutoPageBreak(true);
$mpdf->SetTitle('حسابیکس');
$mpdf->Output('Hesabix PrintOut.pdf', 'I');
@ -60,17 +66,22 @@ class pdfMGR
public function streamTwig2PDFInvoiceType(PrinterQueue $printQueue, $configs = [])
{
$defaultConfig = (new \Mpdf\Config\ConfigVariables())->getDefaults();
$defaultConfig = (new ConfigVariables())->getDefaults();
$fontDirs = $defaultConfig['fontDir'];
$defaultFontConfig = (new \Mpdf\Config\FontVariables())->getDefaults();
$defaultFontConfig = (new FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
$mpdf = new \Mpdf\Mpdf([
'mode' => 'utf-8', 'format' => [80, 300],
'fontDir' => array_merge($fontDirs, [
dirname(__DIR__) . '/Fonts',
]),
'fontdata' => [
$tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mpdf';
if (!is_dir($tempDir)) {
mkdir($tempDir, 0777, true);
}
$mpdf = new Mpdf([
'mode' => 'utf-8',
'format' => [80, 300],
'fontDir' => array_merge($fontDirs, [dirname(__DIR__) . '/Fonts']),
'fontdata' => $fontData + [
'vazirmatn' => [
'R' => 'Vazir-Regular-FD.ttf',
'I' => 'Vazir-Regular-FD.ttf',
@ -79,27 +90,39 @@ class pdfMGR
]
],
'default_font' => 'vazirmatn',
'tempDir' => sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'mpdf',
'tempDir' => $tempDir,
'setAutoTopMargin' => true,
'autoArabic' => true,
'margin-collapse' => 'collapse|none'
]);
$mpdf->AddPageByArray([
'margin-left' => 0,
'margin-right' => 0,
'margin-top' => 0,
'margin-bottom' => 0,
]);
$mpdf->WriteHTML($printQueue->getView());
$htmlContent = $printQueue->getView() ?: '<p>محتوای PDF در دسترس نیست.</p>';
$mpdf->WriteHTML($htmlContent);
$mpdf->Output();
}
private function imageToBase64($path) {
$path = $path;
public function savePDF(PrinterQueue $printQueue, string $path)
{
$mpdf = new Mpdf(['mode' => 'utf-8', 'format' => 'A4']);
$htmlContent = $printQueue->getView() ?: '<p>محتوای PDF در دسترس نیست.</p>';
$mpdf->WriteHTML($htmlContent);
$mpdf->Output($path, \Mpdf\Output\Destination::FILE);
}
private function imageToBase64($path)
{
if (!file_exists($path)) {
return '';
}
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
return $base64;
return 'data:image/' . $type . ';base64,' . base64_encode($data);
}
}
}