backup
Some checks failed
Gitea Actions / Run-Tests-On-Amd64 (push) Failing after 36m1s
Gitea Actions / Merge (push) Successful in 5m39s
Gitea Actions / Run-Tests-On-Arm64 (push) Has been cancelled

This commit is contained in:
Thomas Peterson 2025-12-19 17:03:27 +01:00
parent 6d6241576d
commit 91ba43510b
38 changed files with 2230 additions and 486 deletions

View File

@ -64,10 +64,10 @@ server {
try_files $uri @sfFront;
}
location /w2p/ {
location /w2p/ {
proxy_pass http://tp:8080/w2p/;
proxy_temp_path /tmp/proxy;
}
}
location @sfFront { # Symfony
if ($request_method = 'OPTIONS') {

View File

@ -39,7 +39,6 @@
"knplabs/knp-gaufrette-bundle": "0.9.*",
"knplabs/knp-menu-bundle": "^3",
"knplabs/knp-paginator-bundle": "6.10.*",
"spiriitlabs/form-filter-bundle": "12.0.1",
"lexik/jwt-authentication-bundle": "^3",
"liip/imagine-bundle": "2.16.*",
"mistic100/randomcolor": "^1.1",
@ -63,8 +62,10 @@
"ramsey/uuid": "4.5.1",
"sauladam/shipment-tracker": "dev-master",
"scssphp/scssphp": "v1.11.1",
"setasign/fpdi-tcpdf": "^2.3",
"sofort/sofortlib-php": "3.3.2",
"spatie/array-to-xml": "^3.4",
"spiriitlabs/form-filter-bundle": "12.0.1",
"symfony/asset": "*",
"symfony/asset-mapper": "7.4.*",
"symfony/console": "*",

116
src/new/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1f6b464ced8d089a56009a7fa15b2a34",
"content-hash": "6c648aadd2d1a32e81bdc58fd18f23cc",
"packages": [
{
"name": "apimatic/core",
@ -8327,6 +8327,49 @@
],
"time": "2025-08-05T09:57:14+00:00"
},
{
"name": "setasign/fpdi-tcpdf",
"version": "v2.3.0",
"source": {
"type": "git",
"url": "https://github.com/Setasign/FPDI-TCPDF.git",
"reference": "f6711a95cba64db16e1a63e1b6195827a2150c93"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Setasign/FPDI-TCPDF/zipball/f6711a95cba64db16e1a63e1b6195827a2150c93",
"reference": "f6711a95cba64db16e1a63e1b6195827a2150c93",
"shasum": ""
},
"require": {
"setasign/fpdi": "^2.3",
"tecnickcom/tcpdf": "^6.3.5"
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jan Slabon",
"email": "jan.slabon@setasign.com",
"homepage": "https://www.setasign.com"
}
],
"description": "Kind of metadata package for dependencies of the latest versions of FPDI and TCPDF.",
"homepage": "https://www.setasign.com/fpdi",
"keywords": [
"TCPDF",
"fpdi",
"pdf"
],
"support": {
"source": "https://github.com/Setasign/FPDI-TCPDF/tree/v2.3.0"
},
"abandoned": true,
"time": "2020-02-19T11:40:30+00:00"
},
{
"name": "smalot/pdfparser",
"version": "v2.12.2",
@ -14927,6 +14970,77 @@
},
"time": "2025-01-23T14:54:07+00:00"
},
{
"name": "tecnickcom/tcpdf",
"version": "6.10.1",
"source": {
"type": "git",
"url": "https://github.com/tecnickcom/TCPDF.git",
"reference": "7a2701251e5d52fc3d508fd71704683eb54f5939"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/7a2701251e5d52fc3d508fd71704683eb54f5939",
"reference": "7a2701251e5d52fc3d508fd71704683eb54f5939",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=7.1.0"
},
"type": "library",
"autoload": {
"classmap": [
"config",
"include",
"tcpdf.php",
"tcpdf_barcodes_1d.php",
"tcpdf_barcodes_2d.php",
"include/tcpdf_colors.php",
"include/tcpdf_filters.php",
"include/tcpdf_font_data.php",
"include/tcpdf_fonts.php",
"include/tcpdf_images.php",
"include/tcpdf_static.php",
"include/barcodes/datamatrix.php",
"include/barcodes/pdf417.php",
"include/barcodes/qrcode.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-or-later"
],
"authors": [
{
"name": "Nicola Asuni",
"email": "info@tecnick.com",
"role": "lead"
}
],
"description": "TCPDF is a PHP class for generating PDF documents and barcodes.",
"homepage": "http://www.tcpdf.org/",
"keywords": [
"PDFD32000-2008",
"TCPDF",
"barcodes",
"datamatrix",
"pdf",
"pdf417",
"qrcode"
],
"support": {
"issues": "https://github.com/tecnickcom/TCPDF/issues",
"source": "https://github.com/tecnickcom/TCPDF/tree/6.10.1"
},
"funding": [
{
"url": "https://www.paypal.com/donate/?hosted_button_id=NZUEC5XS8MFBJ",
"type": "custom"
}
],
"time": "2025-11-21T10:58:21+00:00"
},
{
"name": "tp/paydirekt-php",
"version": "4.0.1",

View File

@ -1,9 +1,11 @@
<?php
namespace Plugin\Custom\Albertbauer\Orderexport\Exporter\CSV;
use Port\Reader\ArrayReader;
use Port\Csv\CsvWriter;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use Port\Csv\CsvWriter;
use Port\Reader\ArrayReader;
use PSC\Backend\ToolsBundle\Interfaces\ConfigurableElementInterface as InterfacesConfigurableElementInterface;
use PSC\Backend\ToolsBundle\Interfaces\ExporterInterface as InterfacesExporterInterface;
use PSC\Backend\ToolsBundle\Service\ExporterRegistry;
@ -11,15 +13,13 @@ use PSC\Shop\EntityBundle\Document\Order;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class OrderExport implements InterfacesExporterInterface, InterfacesConfigurableElementInterface
{
private $_formFactory = null;
private $_entityManager = null;
private $_securityContext = null;
@ -27,8 +27,12 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
private $_form = null;
private $mongoService = null;
function __construct(FormFactoryInterface $formFactory, EntityManagerInterface $entityManager, TokenStorageInterface $securityContext, DocumentManager $mongoService)
{
function __construct(
FormFactoryInterface $formFactory,
EntityManagerInterface $entityManager,
TokenStorageInterface $securityContext,
DocumentManager $mongoService,
) {
$this->_formFactory = $formFactory;
$this->_entityManager = $entityManager;
$this->_securityContext = $securityContext;
@ -48,9 +52,10 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
return 'Albertbauer Auftragexport Santis (CSV)';
}
public function getForm(FormBuilderInterface $builder, $form_options) {
$builder->add("from", DateType::class, array('label' => 'Von', 'attr' => array('class' => 'form-element')));
$builder->add("to", DateType::class, array('label' => 'Bis', 'attr' => array('class' => 'form-element')));
public function getForm(FormBuilderInterface $builder, $form_options)
{
$builder->add('from', DateType::class, ['label' => 'Von', 'attr' => ['class' => 'form-element']]);
$builder->add('to', DateType::class, ['label' => 'Bis', 'attr' => ['class' => 'form-element']]);
}
public function getGroup()
@ -58,7 +63,8 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
return ExporterRegistry::$ORDER;
}
public function setForm(Form $form) {
public function setForm(Form $form)
{
$this->_form = $form;
}
@ -67,20 +73,24 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
*/
public function export()
{
$selectedShop = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->mySelectedShop($this->_securityContext->getToken()->getUser());
$selectedShop = $this->_entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->mySelectedShop($this->_securityContext->getToken()->getUser());
$formData = $this->_form->getData();
$orderRepository = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Orderpos');
$results = $orderRepository->createQueryBuilder('o')
->where("o.createdDate >= :from and o.createdDate <= :to and o.shop = :shop")
->setParameter('from', $formData['from'])
->setParameter('to', $formData['to'])
->setParameter('shop', $selectedShop->getId())
->getQuery()->iterate();
$results = $orderRepository
->createQueryBuilder('o')
->where('o.createdDate >= :from and o.createdDate <= :to and o.shop = :shop')
->setParameter('from', $formData['from'])
->setParameter('to', $formData['to'])
->setParameter('shop', $selectedShop->getId())
->getQuery()
->toIterable();
$temp = array();
$temp[]= array(
$temp = [];
$temp[] = [
'create' => 'create',
'brutto' => 'brutto',
'contact' => 'contact',
@ -90,25 +100,28 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
'Strasse' => 'Strasse',
'PLZ / Ort' => 'PLZ / Ort',
'Auftragsnummer' => 'Auftragsnummer',
);
while (false !== ($row = $results->next())) {
];
foreach ($results as $row) {
/** @var \PSC\Shop\EntityBundle\Document\Order $orderObj */
$orderObj = $this->mongoService
->getRepository(Order::class)
->findOneBy(array('uid' => (string)$row[0]->getOrder()->getUid()));
->findOneBy(['uid' => (string) $row->getOrder()->getUid()]);
$temp[]= array(
$row[0]->getOrder()->getCreated()->format('d.m.Y H:i:s'),
$row[0]->getOrder()->getBrutto(),
$row[0]->getOrder()->getContact()->getUsername(),
$row[0]->getProduct()->getUid(),
$row[0]->getProduct()->getTitle(),
$orderObj->getDeliveryAddressSaved()->getFirstname() . ' ' . $orderObj->getDeliveryAddressSaved()->getLastname(),
$orderObj->getDeliveryAddressSaved()->getStreet() . ' ' . $orderObj->getDeliveryAddressSaved()->getHouseNumber(),
$temp[] = [
$row->getOrder()->getCreated()->format('d.m.Y H:i:s'),
$row->getOrder()->getBrutto(),
$row->getOrder()->getContact()->getUsername(),
$row->getProduct()->getUid(),
$row->getProduct()->getTitle(),
$orderObj->getDeliveryAddressSaved()->getFirstname() .
' ' .
$orderObj->getDeliveryAddressSaved()->getLastname(),
$orderObj->getDeliveryAddressSaved()->getStreet() .
' ' .
$orderObj->getDeliveryAddressSaved()->getHouseNumber(),
$orderObj->getDeliveryAddressSaved()->getZip() . ' ' . $orderObj->getDeliveryAddressSaved()->getCity(),
$row[0]->getOrder()->getAlias()
);
$row->getOrder()->getAlias(),
];
}
$reader = new ArrayReader($temp);
@ -116,20 +129,18 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
$writer = new CsvWriter();
$writer->setStream(fopen('php://output', 'w'));
$response = new StreamedResponse(function() use ($reader, $writer) {
foreach($reader as $row) {
$response = new StreamedResponse(function () use ($reader, $writer) {
foreach ($reader as $row) {
$writer->writeItem($row);
}
});
$response->setStatusCode(200);
$response->headers->set('Content-Type', 'text/csv; charset=utf-8');
$disposition = HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
'export.csv'
);
$disposition = HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, 'export.csv');
$response->headers->set('Content-Disposition', $disposition);
return $response;
}
}

View File

@ -1,25 +1,25 @@
<?php
namespace Plugin\Custom\Albertbauer\Orderexport_Unilever\Exporter\CSV;
use Port\Reader\ArrayReader;
use Port\Csv\CsvWriter;
use Doctrine\ORM\EntityManagerInterface;
use Port\Csv\CsvWriter;
use Port\Reader\ArrayReader;
use PSC\Backend\ToolsBundle\Interfaces\ConfigurableElementInterface as InterfacesConfigurableElementInterface;
use PSC\Backend\ToolsBundle\Interfaces\ExporterInterface as InterfacesExporterInterface;
use PSC\Backend\ToolsBundle\Service\ExporterRegistry;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
require_once (__DIR__ .'/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Item.php');
require_once __DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Item.php';
class OrderExport implements InterfacesExporterInterface, InterfacesConfigurableElementInterface
{
private $_formFactory = null;
private $_entityManager = null;
private $_securityContext = null;
@ -32,8 +32,11 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
* @param TokenStorageInterface $securityContext
* @return void
*/
function __construct(FormFactoryInterface $formFactory, EntityManagerInterface $entityManager, TokenStorageInterface $securityContext)
{
function __construct(
FormFactoryInterface $formFactory,
EntityManagerInterface $entityManager,
TokenStorageInterface $securityContext,
) {
$this->_formFactory = $formFactory;
$this->_entityManager = $entityManager;
$this->_securityContext = $securityContext;
@ -52,9 +55,10 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
return 'Albertbauer Auftragexport Unilever (CSV)';
}
public function getForm(FormBuilderInterface $builder, $form_options) {
$builder->add("from", DateType::class, array('label' => 'Von', 'attr' => array('class' => 'form-element')));
$builder->add("to", DateType::class, array('label' => 'Bis', 'attr' => array('class' => 'form-element')));
public function getForm(FormBuilderInterface $builder, $form_options)
{
$builder->add('from', DateType::class, ['label' => 'Von', 'attr' => ['class' => 'form-element']]);
$builder->add('to', DateType::class, ['label' => 'Bis', 'attr' => ['class' => 'form-element']]);
}
public function getGroup()
@ -62,7 +66,8 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
return ExporterRegistry::$ORDER;
}
public function setForm(Form $form) {
public function setForm(Form $form)
{
$this->_form = $form;
}
@ -71,20 +76,24 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
*/
public function export()
{
$selectedShop = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->mySelectedShop($this->_securityContext->getToken()->getUser());
$selectedShop = $this->_entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->mySelectedShop($this->_securityContext->getToken()->getUser());
$formData = $this->_form->getData();
$orderRepository = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Orderpos');
$results = $orderRepository->createQueryBuilder('o')
->where("o.createdDate >= :from and o.createdDate <= :to and o.shop = :shop")
->setParameter('from', $formData['from'])
->setParameter('to', $formData['to'])
->setParameter('shop', $selectedShop->getId())
->getQuery()->iterate();
$results = $orderRepository
->createQueryBuilder('o')
->where('o.createdDate >= :from and o.createdDate <= :to and o.shop = :shop')
->setParameter('from', $formData['from'])
->setParameter('to', $formData['to'])
->setParameter('shop', $selectedShop->getId())
->getQuery()
->toIterable();
$temp = array();
$temp[]= array(
$temp = [];
$temp[] = [
'Auftrag Nr' => 'Auftrag Nr',
'Auftragsname / -typ' => 'Auftragsname / -typ',
'Auftraggeber' => 'Auftraggeber',
@ -95,23 +104,23 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
'Sonderversandkosten Netto' => 'Sonderversandkosten Netto',
'WK Gesamt Netto' => 'WK Gesamt Netto',
'Netto' => 'Netto',
);
];
while (false !== ($row = $results->next())) {
$objPosition = unserialize(($row[0]->getData()));
foreach ($results as $row) {
$objPosition = unserialize($row->getData());
//var_dump($objPosition->getAuflage());
$temp[]= array(
$row[0]->getOrder()->getAlias(),
$row[0]->getProduct()->getTitle(),
$row[0]->getOrder()->getContact()->getUsername(),
$row[0]->getBasketField2(), //KOSTENSTELLE!!!
$row[0]->getOrder()->getCreated()->format('d.m.Y'),
$objPosition->getOptions()["auflage"],
$row[0]->getPriceOneNetto(),
$row[0]->getOrder()->getVersandKosten(),
$row[0]->getOrder()->getBrutto(),
$row[0]->getOrder()->getNetto()
);
$temp[] = [
$row->getOrder()->getAlias(),
$row->getProduct()->getTitle(),
$row->getOrder()->getContact()->getUsername(),
$row->getBasketField2(), //KOSTENSTELLE!!!
$row->getOrder()->getCreated()->format('d.m.Y'),
$objPosition->getOptions()['auflage'],
$row->getPriceOneNetto(),
$row->getOrder()->getVersandKosten(),
$row->getOrder()->getBrutto(),
$row->getOrder()->getNetto(),
];
}
$reader = new ArrayReader($temp);
@ -119,20 +128,18 @@ class OrderExport implements InterfacesExporterInterface, InterfacesConfigurable
$writer = new CsvWriter();
$writer->setStream(fopen('php://output', 'w'));
$response = new StreamedResponse(function() use ($reader, $writer) {
foreach($reader as $row) {
$response = new StreamedResponse(function () use ($reader, $writer) {
foreach ($reader as $row) {
$writer->writeItem($row);
}
});
$response->setStatusCode(200);
$response->headers->set('Content-Type', 'text/csv; charset=utf-8');
$disposition = HeaderUtils::makeDisposition(
HeaderUtils::DISPOSITION_ATTACHMENT,
'export.csv'
);
$disposition = HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, 'export.csv');
$response->headers->set('Content-Disposition', $disposition);
return $response;
}
}

View File

@ -4,7 +4,7 @@ namespace Plugin\Custom\PSC\CollectLayouter\Api;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Attribute\Model;
use OpenApi\Attributes\Items;
use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\RequestBody;
@ -19,10 +19,10 @@ use Plugin\Custom\PSC\CollectLayouter\Model\Setting;
use PSC\Shop\ContactBundle\Repository\ContactRepository;
use PSC\Shop\ContactBundle\Transformer\Model\Contact;
use PSC\Shop\EntityBundle\Entity\Product;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
@ -39,12 +39,14 @@ class Form extends AbstractController
) {}
#[Route(path: '/form/{uuid}/{contactUuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'return customerForm', ref: new Items(ref: new Model(type: Element::class)))]
public function generateForm(Input $input, string $uuid, string $contactUuid = ''): JsonResponse
{
public function generateForm(
#[MapRequestPayload] Input $input,
string $uuid,
string $contactUuid = '',
): JsonResponse {
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager
@ -193,12 +195,14 @@ class Form extends AbstractController
}
#[Route(path: '/newform/{uuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'return customerForm', ref: new Items(ref: new Model(type: Element::class)))]
public function generateNewForm(Input $input, string $uuid, string $contactUuid = ''): JsonResponse
{
public function generateNewForm(
#[MapRequestPayload] Input $input,
string $uuid,
string $contactUuid = '',
): JsonResponse {
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager

View File

@ -4,7 +4,7 @@ namespace Plugin\Custom\PSC\CollectLayouter\Api;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use Nelmio\ApiDocBundle\Model\Model;
use Nelmio\ApiDocBundle\Attribute\Model;
use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\RequestBody;
use OpenApi\Attributes\Response;
@ -19,12 +19,12 @@ use PSC\Shop\ContactBundle\Transformer\Model\Contact;
use PSC\Shop\EntityBundle\Entity\Product;
use PSC\Shop\MediaBundle\Model\Media;
use PSC\Shop\MediaBundle\Service\MediaManager;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
@ -44,12 +44,15 @@ class Preview extends AbstractController
) {}
#[Route(path: '/preview/{uuid}/{type}/{contactUuid}', methods: ['PUT'], defaults: ['contactUuid' => ''])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'return previews', content: new JsonContent(type: 'bool'))]
public function generatePreview(Input $data, string $uuid, string $contactUuid = '', int $type = 1): JsonResponse
{
public function generatePreview(
#[MapRequestPayload] Input $data,
string $uuid,
string $contactUuid = '',
int $type = 1,
): JsonResponse {
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager

View File

@ -18,11 +18,11 @@ use PSC\Shop\EntityBundle\Entity\Layoutdesigndata;
use PSC\Shop\EntityBundle\Entity\LayouterSession;
use PSC\Shop\EntityBundle\Entity\Product;
use PSC\Shop\MediaBundle\Service\MediaManager;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\SerializerInterface;
use Twig\Environment;
@ -41,11 +41,10 @@ class Save extends AbstractController
) {}
#[Route(path: '/savecollect/{uuid}/{contactuuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'save config in session', content: new JsonContent(type: 'bool'))]
public function saveCollect(Input $data, string $uuid, string $contactuuid): JsonResponse
public function saveCollect(#[MapRequestPayload] Input $data, string $uuid, string $contactuuid): JsonResponse
{
$basketField1 = '';
$basketField2 = '';
@ -224,11 +223,10 @@ class Save extends AbstractController
}
#[Route(path: '/save/{uuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'save config in session', content: new JsonContent(type: 'bool'))]
public function save(Input $data, string $uuid): JsonResponse
public function save(#[MapRequestPayload] Input $data, string $uuid): JsonResponse
{
$basketField1 = '';
$basketField2 = '';

View File

@ -8,54 +8,57 @@ use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\RequestBody;
use OpenApi\Attributes\Response;
use OpenApi\Attributes\Tag;
use PSC\Shop\EntityBundle\Entity\Contact as PSCContact;
use Plugin\Custom\PSC\CollectLayouter\Dto\SaveContact\Input;
use Plugin\Custom\PSC\CollectLayouter\Model\Setting;
use PSC\Shop\ContactBundle\Model\Role;
use PSC\Shop\ContactBundle\Transformer\Model\Contact;
use PSC\Shop\EntityBundle\Entity\Contact as PSCContact;
use PSC\Shop\EntityBundle\Entity\Layoutdesigndata;
use PSC\Shop\EntityBundle\Entity\LayouterSession;
use PSC\Shop\EntityBundle\Entity\Product;
use PSC\System\SettingsBundle\Service\Shop;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\SerializerInterface;
class SaveContact extends AbstractController
{
public function __construct(
readonly private \Plugin\Custom\PSC\CollectLayouter\Helper\SaveContact $saveContactHelper,
private readonly \Plugin\Custom\PSC\CollectLayouter\Helper\SaveContact $saveContactHelper,
private EntityManagerInterface $entityManager,
private DocumentManager $documentManager,
private SerializerInterface $serializer,
private Contact $contactTransformer,
private RequestStack $requestStack,
private Shop $shopService
) {
}
private Shop $shopService,
) {}
#[Route(path: '/savecontact/{uuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'save config in session', content: new JsonContent(type: 'bool'))]
public function save(Input $data, string $uuid): JsonResponse
public function save(#[MapRequestPayload] Input $data, string $uuid): JsonResponse
{
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize($productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}', Setting::class, 'json');
$productDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)
->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize(
$productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}',
Setting::class,
'json',
);
$contact = new \PSC\Shop\ContactBundle\Model\Contact();
if ($this->getUser()) {
$this->contactTransformer->fromDb($contact, $this->getUser());
}
if ($contact->getUuid() != "") {
if ($contact->getUuid() != '') {
$this->saveContactHelper->setSetting($setting);
$this->saveContactHelper->setContact($contact);
$this->saveContactHelper->setData($data);
@ -66,22 +69,26 @@ class SaveContact extends AbstractController
}
#[Route(path: '/savecontactcollect/{uuid}/{contactuuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'save config in session', content: new JsonContent(type: 'bool'))]
public function saveCollect(Input $data, string $uuid, string $contactuuid): JsonResponse
public function saveCollect(#[MapRequestPayload] Input $data, string $uuid, string $contactuuid): JsonResponse
{
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize($productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}', Setting::class, 'json');
$productDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)
->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize(
$productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}',
Setting::class,
'json',
);
$contactEntity = $this->entityManager->getRepository(PSCContact::class)->findOneBy(['uuid' => $contactuuid]);
$contact = new \PSC\Shop\ContactBundle\Model\Contact();
$this->contactTransformer->fromDb($contact, $contactEntity);
if ($contact->getUuid() != "") {
if ($contact->getUuid() != '') {
$this->saveContactHelper->setSetting($setting);
$this->saveContactHelper->setContact($contact);
$this->saveContactHelper->setData($data);
@ -92,17 +99,21 @@ class SaveContact extends AbstractController
}
#[Route(path: '/savenewcontact/{uuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'save config in session', content: new JsonContent(type: 'bool'))]
public function saveNew(Input $data, string $uuid): JsonResponse
public function saveNew(#[MapRequestPayload] Input $data, string $uuid): JsonResponse
{
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize($productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}', Setting::class, 'json');
$productDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)
->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize(
$productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}',
Setting::class,
'json',
);
$contact = new \PSC\Shop\ContactBundle\Model\Contact();
$shop = new \PSC\Component\ApiBundle\Model\Shop();
@ -121,5 +132,4 @@ class SaveContact extends AbstractController
return $this->json(['success' => true]);
}
}

View File

@ -4,7 +4,7 @@ namespace Plugin\Custom\PSC\CollectLayouter\Api;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Attribute\Model;
use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\RequestBody;
use OpenApi\Attributes\Response;
@ -12,10 +12,10 @@ use OpenApi\Attributes\Tag;
use Plugin\Custom\PSC\CollectLayouter\Dto\Preview\Input;
use Plugin\Custom\PSC\CollectLayouter\Model\Setting;
use PSC\Shop\EntityBundle\Entity\Product;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
@ -54,14 +54,13 @@ class Settings extends AbstractController
#[Route(path: '/settings/{uuid}', methods: ['PUT'])]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[ParamConverter('data', class: Setting::class, converter: 'psc_rest.request_body')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Setting::class))]
#[Response(
response: 200,
description: 'return settings',
content: new JsonContent(ref: new Model(type: Setting::class)),
)]
public function save(string $uuid, Setting $data): JsonResponse
public function save(string $uuid, #[MapRequestPayload] Setting $data): JsonResponse
{
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
@ -85,4 +84,3 @@ class Settings extends AbstractController
return $this->json($data);
}
}

View File

@ -8,45 +8,52 @@ use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\RequestBody;
use OpenApi\Attributes\Response;
use OpenApi\Attributes\Tag;
use PSC\Shop\EntityBundle\Entity\Contact as PSCContact;
use Plugin\Custom\PSC\CollectLayouter\Dto\Save\Input;
use Plugin\Custom\PSC\CollectLayouter\Model\Setting;
use PSC\Shop\ContactBundle\Transformer\Model\Contact;
use PSC\Shop\EntityBundle\Entity\Contact as PSCContact;
use PSC\Shop\EntityBundle\Entity\LayouterSession;
use PSC\Shop\EntityBundle\Entity\Product;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\SerializerInterface;
class Update extends AbstractController
{
public function __construct(
readonly private \Plugin\Custom\PSC\CollectLayouter\Helper\SaveFiles $saveFilesHelper,
readonly private \Plugin\Custom\PSC\CollectLayouter\Helper\SaveContact $saveContactHelper,
private readonly \Plugin\Custom\PSC\CollectLayouter\Helper\SaveFiles $saveFilesHelper,
private readonly \Plugin\Custom\PSC\CollectLayouter\Helper\SaveContact $saveContactHelper,
private EntityManagerInterface $entityManager,
private DocumentManager $documentManager,
private SerializerInterface $serializer,
private Contact $contactTransformer
) {
}
private Contact $contactTransformer,
) {}
#[Route(path: '/update/{uuid}/{layouterUuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'save config in session', content: new JsonContent(type: 'bool'))]
public function update(Input $data, string $uuid, string $layouterUuid): JsonResponse
public function update(#[MapRequestPayload] Input $data, string $uuid, string $layouterUuid): JsonResponse
{
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize($productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}', Setting::class, 'json');
$productDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)
->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize(
$productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}',
Setting::class,
'json',
);
$contact = new \PSC\Shop\ContactBundle\Model\Contact();
if ($this->getUser()) {
$this->contactTransformer->fromDb($contact, $this->getUser(), new \PSC\Shop\EntityBundle\Document\Contact());
$this->contactTransformer->fromDb(
$contact,
$this->getUser(),
new \PSC\Shop\EntityBundle\Document\Contact(),
);
}
$this->saveFilesHelper->setSetting($setting);
$this->saveFilesHelper->setContact($contact);
@ -54,7 +61,7 @@ class Update extends AbstractController
$this->saveFilesHelper->storeFiles();
if ($contact->getUuid() != "") {
if ($contact->getUuid() != '') {
$this->saveContactHelper->setSetting($setting);
$this->saveContactHelper->setContact($contact);
$this->saveContactHelper->setData($data);
@ -62,21 +69,30 @@ class Update extends AbstractController
}
$layoutDesignData = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Layoutdesigndata')->findOneBy(array('uuid' => $layouterUuid));
->getRepository('PSC\Shop\EntityBundle\Entity\Layoutdesigndata')
->findOneBy(['uuid' => $layouterUuid]);
$layoutDesignData->setDesign(['data' => $data->getData(), 'contactUuid' => $data->getContactUuid(), 'pdf' => $this->saveFilesHelper->getPdfFile(), 'previews' => $this->saveFilesHelper->getImages()]);
$layoutDesignData->setDesign([
'data' => $data->getData(),
'contactUuid' => $data->getContactUuid(),
'pdf' => $this->saveFilesHelper->getPdfFile(),
'previews' => $this->saveFilesHelper->getImages(),
]);
$this->entityManager->persist($layoutDesignData);
$this->entityManager->flush();
$layouterSession = $this->entityManager->getRepository(LayouterSession::class)->findOneBy(['uuid' => $layouterUuid]);
$layouterSession = $this->entityManager
->getRepository(LayouterSession::class)
->findOneBy(['uuid' => $layouterUuid]);
$layouterDesignDataDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\LayouterSession::class)
$layouterDesignDataDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\LayouterSession::class)
->findOneBy(['uid' => $layouterSession->getUID()]);
if (!$layouterDesignDataDoc) {
$layouterDesignDataDoc = new \PSC\Shop\EntityBundle\Document\LayouterSession();
$layouterDesignDataDoc->setUid((string)$layoutDesignData->getUID());
$layouterDesignDataDoc->setUid((string) $layoutDesignData->getUID());
}
$layouterDesignDataDoc->setKst($data->getKst());
$layouterDesignDataDoc->setRef($data->getRef());
@ -88,17 +104,25 @@ class Update extends AbstractController
}
#[Route(path: '/updatecollect/{uuid}/{layouterUuid}/{contactUuid}', methods: ['PUT'])]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/CollectLayouter')]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'save config in session', content: new JsonContent(type: 'bool'))]
public function updateCollect(Input $data, string $uuid, string $layouterUuid, string $contactUuid): JsonResponse
{
public function updateCollect(
#[MapRequestPayload] Input $data,
string $uuid,
string $layouterUuid,
string $contactUuid,
): JsonResponse {
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $uuid]);
$productDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize($productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}', Setting::class, 'json');
$productDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)
->findOneBy(['uid' => $product->getUID()]);
$setting = $this->serializer->deserialize(
$productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}',
Setting::class,
'json',
);
$contactEntity = $this->entityManager->getRepository(PSCContact::class)->findOneBy(['uuid' => $contactUuid]);
$contact = new \PSC\Shop\ContactBundle\Model\Contact();
$this->contactTransformer->fromDb($contact, $contactEntity);
@ -109,7 +133,7 @@ class Update extends AbstractController
$this->saveFilesHelper->storeFiles();
if ($contact->getUuid() != "") {
if ($contact->getUuid() != '') {
$this->saveContactHelper->setSetting($setting);
$this->saveContactHelper->setContact($contact);
$this->saveContactHelper->setData($data);
@ -117,21 +141,30 @@ class Update extends AbstractController
}
$layoutDesignData = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Layoutdesigndata')->findOneBy(array('uuid' => $layouterUuid));
->getRepository('PSC\Shop\EntityBundle\Entity\Layoutdesigndata')
->findOneBy(['uuid' => $layouterUuid]);
$layoutDesignData->setDesign(['data' => $data->getData(), 'contactUuid' => $data->getContactUuid(), 'pdf' => $this->saveFilesHelper->getPdfFile(), 'previews' => $this->saveFilesHelper->getImages()]);
$layoutDesignData->setDesign([
'data' => $data->getData(),
'contactUuid' => $data->getContactUuid(),
'pdf' => $this->saveFilesHelper->getPdfFile(),
'previews' => $this->saveFilesHelper->getImages(),
]);
$this->entityManager->persist($layoutDesignData);
$this->entityManager->flush();
$layouterSession = $this->entityManager->getRepository(LayouterSession::class)->findOneBy(['uuid' => $layouterUuid]);
$layouterSession = $this->entityManager
->getRepository(LayouterSession::class)
->findOneBy(['uuid' => $layouterUuid]);
$layouterDesignDataDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\LayouterSession::class)
$layouterDesignDataDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\LayouterSession::class)
->findOneBy(['uid' => $layouterSession->getUID()]);
if (!$layouterDesignDataDoc) {
$layouterDesignDataDoc = new \PSC\Shop\EntityBundle\Document\LayouterSession();
$layouterDesignDataDoc->setUid((string)$layoutDesignData->getUID());
$layouterDesignDataDoc->setUid((string) $layoutDesignData->getUID());
}
$layouterDesignDataDoc->setKst($data->getKst());
$layouterDesignDataDoc->setRef($data->getRef());
@ -141,5 +174,4 @@ class Update extends AbstractController
return $this->json(['success' => true]);
}
}

View File

@ -8,11 +8,11 @@ use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Plugin\Custom\PSC\CollectLayouter\Form\ContactSelectType;
use Plugin\Custom\PSC\CollectLayouter\Model\Setting;
use PSC\Shop\EntityBundle\Entity\Product;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Serializer\SerializerInterface;
#[Route('/product')]
@ -24,7 +24,7 @@ class IndexController extends AbstractController
private SerializerInterface $serializer,
) {}
#[Template]
#[Template('@PluginCustomPSCCollectLayouter/backend/index/index.html.twig')]
#[IsGranted('ROLE_ADMIN')]
#[Route(
'/edit/{uuid}',

View File

@ -20,7 +20,7 @@ use Ramsey\Uuid\Uuid;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\SerializerInterface;
#[Route('/designer')]
@ -36,7 +36,7 @@ class DesignerController extends AbstractController
private readonly MediaManager $mediaManager,
) {}
#[Template]
#[Template('@PluginCustomPSCCollectLayouter/frontend/designer/start.html.twig')]
#[Route('/start/{productUuid}/{contactUuid}', name: 'plugin_custom_psc_collectlayouter_start', defaults: [
'contactUuid' => '',
])]
@ -77,7 +77,7 @@ class DesignerController extends AbstractController
];
}
#[Template]
#[Template('@PluginCustomPSCCollectLayouter/frontend/designer/collect.html.twig')]
#[Route(
'/startcollect/{productUuid}/{mode}/{contactUuid}',
name: 'plugin_custom_psc_collectlayouter_collect',
@ -120,7 +120,7 @@ class DesignerController extends AbstractController
];
}
#[Template]
#[Template('@PluginCustomPSCCollectLayouter/frontend/designer/load_collect.html.twig')]
#[Route('/loadcollect/{productId}/{layouterId}', name: 'plugin_custom_psc_collectlayouter_loadcollect', defaults: [
'contactUuid' => '',
])]
@ -164,7 +164,7 @@ class DesignerController extends AbstractController
];
}
#[Template]
#[Template('@PluginCustomPSCCollectLayouter/frontend/designer/load.html.twig')]
#[Route('/load/{productId}/{layouterId}/{contactUuid}', name: 'plugin_custom_psc_collectlayouter_load', defaults: [
'contactUuid' => '',
])]

View File

@ -6,41 +6,46 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use MongoDB\BSON\Regex;
use PSC\Shop\ContactBundle\Service\Contact;
use PSC\Shop\EntityBundle\Document\Contact as PSCContact;
use Plugin\Custom\PSC\CollectLayouter\Form\UserType;
use Plugin\Custom\PSC\CollectLayouter\Model\Setting;
use Plugin\Custom\PSC\CollectLayouter\VCard\VCard;
use PSC\Shop\AccountBundle\Model\Account;
use PSC\Shop\ContactBundle\Service\Contact;
use PSC\Shop\EntityBundle\Document\Contact as PSCContact;
use PSC\Shop\EntityBundle\Entity\ContactRole;
use PSC\Shop\EntityBundle\Entity\Product;
use PSC\Shop\EntityBundle\Entity\ShopContact;
use PSC\System\SettingsBundle\Service\Shop;
use Ramsey\Uuid\Uuid;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Serializer\SerializerInterface;
#[Route('/user')]
class UserController extends AbstractController
{
public function __construct(private SerializerInterface $serializer, private readonly \PSC\Shop\ContactBundle\Transformer\Model\Contact $contactTransformer, private readonly DocumentManager $documentManager, private readonly EntityManagerInterface $entityManager, private readonly Shop $shopService)
{
}
public function __construct(
private SerializerInterface $serializer,
private readonly \PSC\Shop\ContactBundle\Transformer\Model\Contact $contactTransformer,
private readonly DocumentManager $documentManager,
private readonly EntityManagerInterface $entityManager,
private readonly Shop $shopService,
) {}
#[Template('@PluginCustomPSCCollectLayouterControllerFrontend/user/edit.html.twig')]
#[Template('@PluginCustomPSCCollectLayouter/fontend/user/edit.html.twig')]
#[Route('/edit/{productUuid}/{contactUuid}', name: 'plugin_custom_psc_collectlayouter_user_edit')]
#[IsGranted('ROLE_PSC_Collect_Contact_Edit')]
public function edit(Request $request, string $contactUuid, string $productUuid = ''): array
{
$save = false;
/** @var Contact $contact */
$contact = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->findOneBy(array('uuid' => $contactUuid));
$contact = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->findOneBy(['uuid' => $contactUuid]);
$contactModel = new \PSC\Shop\ContactBundle\Model\Contact();
$this->contactTransformer->fromDb($contactModel, $contact);
@ -98,7 +103,6 @@ class UserController extends AbstractController
$data['abteilungEnable'] = true;
}
$pos3Enable = array_values(array_filter($docData, function ($elm) {
if ($elm['name'] == 'data[position3][enable]') {
return $elm;
@ -109,7 +113,6 @@ class UserController extends AbstractController
$data['functionEnable'] = true;
}
$officeEnable = array_values(array_filter($docData, function ($elm) {
if ($elm['name'] == 'data[office][enable]') {
return $elm;
@ -150,7 +153,6 @@ class UserController extends AbstractController
$data['faxEnable'] = true;
}
$form = $this->createForm(UserType::class, $data);
$form->handleRequest($request);
@ -161,75 +163,74 @@ class UserController extends AbstractController
$account->setUid($data['account']->getId());
$contactModel->setAccount($account);
$contactModel->getLayouterData()->setSalutation($data['salutation']);
$contactModel->getLayouterData()->setTitle((string)$data['title']);
$contactModel->getLayouterData()->setFirstname((string)$data['firstname']);
$contactModel->getLayouterData()->setLastname((string)$data['lastname']);
$contactModel->getLayouterData()->setCompany((string)$data['company']);
$contactModel->getLayouterData()->setCompany2((string)$data['company2']);
$contactModel->getLayouterData()->setFunction((string)$data['function']);
$contactModel->getLayouterData()->setAbteilung((string)$data['abteilung']);
$contactModel->getLayouterData()->setPosition((string)$data['position']);
$contactModel->getLayouterData()->setStreet((string)$data['street']);
$contactModel->getLayouterData()->setHouseNumber((string)$data['houseNumber']);
$contactModel->getLayouterData()->setZip((string)$data['zip']);
$contactModel->getLayouterData()->setCity((string)$data['city']);
$contactModel->setEmail((string)$data['email']);
$contactModel->getLayouterData()->setPhone((string)$data['phone']);
$contactModel->getLayouterData()->setPhonePrefix((string)$data['phonePrefix']);
$contactModel->getLayouterData()->setPhoneAppendix((string)$data['phoneAppendix']);
$contactModel->getLayouterData()->setPhoneAreaCode((string)$data['phoneAreaCode']);
$contactModel->getLayouterData()->setFax((string)$data['fax']);
$contactModel->getLayouterData()->setFaxPrefix((string)$data['faxPrefix']);
$contactModel->getLayouterData()->setFaxAppendix((string)$data['faxAppendix']);
$contactModel->getLayouterData()->setFaxAreaCode((string)$data['faxAreaCode']);
$contactModel->getLayouterData()->setMobile((string)$data['mobile']);
$contactModel->getLayouterData()->setMobilePrefix((string)$data['mobilePrefix']);
$contactModel->getLayouterData()->setMobileAppendix((string)$data['mobileAppendix']);
$contactModel->getLayouterData()->setMobileAreaCode((string)$data['mobileAreaCode']);
$contactModel->getLayouterData()->setCountryCode((string)$data['country']);
$contactModel->getLayouterData()->setTitle((string) $data['title']);
$contactModel->getLayouterData()->setFirstname((string) $data['firstname']);
$contactModel->getLayouterData()->setLastname((string) $data['lastname']);
$contactModel->getLayouterData()->setCompany((string) $data['company']);
$contactModel->getLayouterData()->setCompany2((string) $data['company2']);
$contactModel->getLayouterData()->setFunction((string) $data['function']);
$contactModel->getLayouterData()->setAbteilung((string) $data['abteilung']);
$contactModel->getLayouterData()->setPosition((string) $data['position']);
$contactModel->getLayouterData()->setStreet((string) $data['street']);
$contactModel->getLayouterData()->setHouseNumber((string) $data['houseNumber']);
$contactModel->getLayouterData()->setZip((string) $data['zip']);
$contactModel->getLayouterData()->setCity((string) $data['city']);
$contactModel->setEmail((string) $data['email']);
$contactModel->getLayouterData()->setPhone((string) $data['phone']);
$contactModel->getLayouterData()->setPhonePrefix((string) $data['phonePrefix']);
$contactModel->getLayouterData()->setPhoneAppendix((string) $data['phoneAppendix']);
$contactModel->getLayouterData()->setPhoneAreaCode((string) $data['phoneAreaCode']);
$contactModel->getLayouterData()->setFax((string) $data['fax']);
$contactModel->getLayouterData()->setFaxPrefix((string) $data['faxPrefix']);
$contactModel->getLayouterData()->setFaxAppendix((string) $data['faxAppendix']);
$contactModel->getLayouterData()->setFaxAreaCode((string) $data['faxAreaCode']);
$contactModel->getLayouterData()->setMobile((string) $data['mobile']);
$contactModel->getLayouterData()->setMobilePrefix((string) $data['mobilePrefix']);
$contactModel->getLayouterData()->setMobileAppendix((string) $data['mobileAppendix']);
$contactModel->getLayouterData()->setMobileAreaCode((string) $data['mobileAreaCode']);
$contactModel->getLayouterData()->setCountryCode((string) $data['country']);
$docData = [];
if (isset($data['titleEnable']) && $data['titleEnable']) {
$docData[] = [
'name' => 'data[title][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['abteilungEnable']) && $data['abteilungEnable']) {
$docData[] = [
'name' => 'data[position2][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['functionEnable']) && $data['functionEnable']) {
$docData[] = [
'name' => 'data[position3][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['company2Enable']) && $data['company2Enable']) {
$docData[] = [
'name' => 'data[office][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['phoneEnable']) && $data['phoneEnable']) {
$docData[] = [
'name' => 'data[fon][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['mobileEnable']) && $data['mobileEnable']) {
$docData[] = [
'name' => 'data[mobile][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['faxEnable']) && $data['faxEnable']) {
$docData[] = [
'name' => 'data[fax][enable]',
'value' => '1'
'value' => '1',
];
}
$contactModel->getLayouterData()->addSettingForLayouter('collectlayouter', $docData);
@ -239,14 +240,14 @@ class UserController extends AbstractController
$save = true;
}
return array(
return [
'form' => $form->createView(),
'save' => $save,
'productUuid' => $productUuid
);
'productUuid' => $productUuid,
];
}
#[Template('@PluginCustomPSCCollectLayouterControllerFrontend/user/new.html.twig')]
#[Template('@PluginCustomPSCCollectLayouter/fontend/user/new.html.twig')]
#[Route('/new/{productUuid}', name: 'plugin_custom_psc_collectlayouter_user_new')]
#[IsGranted('ROLE_PSC_Collect_Contact_Add')]
public function new(Request $request, Shop $shopService, string $productUuid = '')
@ -264,10 +265,15 @@ class UserController extends AbstractController
if ($form->isSubmitted()) {
$data = $form->getData();
$contactEx = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')->where("contact.username = :username and shop.uid = :shop")
->setParameter('username', $data['email'])->setParameter('shop', $selectedShop->getUID())
->getQuery()->getOneOrNullResult();
$contactEx = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')
->where('contact.username = :username and shop.uid = :shop')
->setParameter('username', $data['email'])
->setParameter('shop', $selectedShop->getUID())
->getQuery()
->getOneOrNullResult();
if ($contactEx) {
$contactExists = true;
@ -313,120 +319,123 @@ class UserController extends AbstractController
$account->setUid($data['account']->getId());
$contactModel->setAccount($account);
$contactModel->getLayouterData()->setSalutation($data['salutation']);
$contactModel->getLayouterData()->setTitle((string)$data['title']);
$contactModel->getLayouterData()->setFirstname((string)$data['firstname']);
$contactModel->getLayouterData()->setLastname((string)$data['lastname']);
$contactModel->getLayouterData()->setCompany((string)$data['company']);
$contactModel->getLayouterData()->setCompany2((string)$data['company2']);
$contactModel->getLayouterData()->setFunction((string)$data['function']);
$contactModel->getLayouterData()->setAbteilung((string)$data['abteilung']);
$contactModel->getLayouterData()->setPosition((string)$data['position']);
$contactModel->getLayouterData()->setStreet((string)$data['street']);
$contactModel->getLayouterData()->setHouseNumber((string)$data['houseNumber']);
$contactModel->getLayouterData()->setZip((string)$data['zip']);
$contactModel->getLayouterData()->setCity((string)$data['city']);
$contactModel->setEmail((string)$data['email']);
$contactModel->getLayouterData()->setPhone((string)$data['phone']);
$contactModel->getLayouterData()->setPhonePrefix((string)$data['phonePrefix']);
$contactModel->getLayouterData()->setPhoneAppendix((string)$data['phoneAppendix']);
$contactModel->getLayouterData()->setPhoneAreaCode((string)$data['phoneAreaCode']);
$contactModel->getLayouterData()->setFax((string)$data['fax']);
$contactModel->getLayouterData()->setFaxPrefix((string)$data['faxPrefix']);
$contactModel->getLayouterData()->setFaxAppendix((string)$data['faxAppendix']);
$contactModel->getLayouterData()->setFaxAreaCode((string)$data['faxAreaCode']);
$contactModel->getLayouterData()->setMobile((string)$data['mobile']);
$contactModel->getLayouterData()->setMobilePrefix((string)$data['mobilePrefix']);
$contactModel->getLayouterData()->setMobileAppendix((string)$data['mobileAppendix']);
$contactModel->getLayouterData()->setMobileAreaCode((string)$data['mobileAreaCode']);
$contactModel->getLayouterData()->setCountry((string)$data['country']);
$contactModel->getLayouterData()->setTitle((string) $data['title']);
$contactModel->getLayouterData()->setFirstname((string) $data['firstname']);
$contactModel->getLayouterData()->setLastname((string) $data['lastname']);
$contactModel->getLayouterData()->setCompany((string) $data['company']);
$contactModel->getLayouterData()->setCompany2((string) $data['company2']);
$contactModel->getLayouterData()->setFunction((string) $data['function']);
$contactModel->getLayouterData()->setAbteilung((string) $data['abteilung']);
$contactModel->getLayouterData()->setPosition((string) $data['position']);
$contactModel->getLayouterData()->setStreet((string) $data['street']);
$contactModel->getLayouterData()->setHouseNumber((string) $data['houseNumber']);
$contactModel->getLayouterData()->setZip((string) $data['zip']);
$contactModel->getLayouterData()->setCity((string) $data['city']);
$contactModel->setEmail((string) $data['email']);
$contactModel->getLayouterData()->setPhone((string) $data['phone']);
$contactModel->getLayouterData()->setPhonePrefix((string) $data['phonePrefix']);
$contactModel->getLayouterData()->setPhoneAppendix((string) $data['phoneAppendix']);
$contactModel->getLayouterData()->setPhoneAreaCode((string) $data['phoneAreaCode']);
$contactModel->getLayouterData()->setFax((string) $data['fax']);
$contactModel->getLayouterData()->setFaxPrefix((string) $data['faxPrefix']);
$contactModel->getLayouterData()->setFaxAppendix((string) $data['faxAppendix']);
$contactModel->getLayouterData()->setFaxAreaCode((string) $data['faxAreaCode']);
$contactModel->getLayouterData()->setMobile((string) $data['mobile']);
$contactModel->getLayouterData()->setMobilePrefix((string) $data['mobilePrefix']);
$contactModel->getLayouterData()->setMobileAppendix((string) $data['mobileAppendix']);
$contactModel->getLayouterData()->setMobileAreaCode((string) $data['mobileAreaCode']);
$contactModel->getLayouterData()->setCountry((string) $data['country']);
$docData = [];
if (isset($data['titleEnable']) && $data['titleEnable']) {
$docData[] = [
'name' => 'data[title][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['abteilungEnable']) && $data['abteilungEnable']) {
$docData[] = [
'name' => 'data[position2][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['functionEnable']) && $data['functionEnable']) {
$docData[] = [
'name' => 'data[position3][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['company2Enable']) && $data['company2Enable']) {
$docData[] = [
'name' => 'data[office][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['phoneEnable']) && $data['phoneEnable']) {
$docData[] = [
'name' => 'data[fon][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['mobileEnable']) && $data['mobileEnable']) {
$docData[] = [
'name' => 'data[mobile][enable]',
'value' => '1'
'value' => '1',
];
}
if (isset($data['faxEnable']) && $data['faxEnable']) {
$docData[] = [
'name' => 'data[fax][enable]',
'value' => '1'
'value' => '1',
];
}
$contactModel->getLayouterData()->addSettingForLayouter('collectlayouter', $docData);
$this->contactTransformer->toDb($contactModel);
$save = true;
}
return array(
return [
'form' => $form->createView(),
'save' => $save,
'productUuid' => $productUuid,
'contactExists' => $contactExists
);
'contactExists' => $contactExists,
];
}
#[Template('@PluginCustomPSCCollectLayouterControllerFrontend/user/list.html.twig')]
#[Template('@PluginCustomPSCCollectLayouter/frontend/user/list.html.twig')]
#[Route('/list/{productUuid}/{orderBy}/{sort}', name: 'plugin_custom_psc_collectlayouter_user_list')]
public function list(Request $request, string $productUuid = 'none', $orderBy = 'uid', $sort = 'asc'): array
{
if ($this->getUser() == null || !$this->getUser()->getIsSek()) {
throw new AccessDeniedException("Not Sek");
throw new AccessDeniedException('Not Sek');
}
$product = false;
if ($productUuid != "none") {
if ($productUuid != 'none') {
$product = $this->entityManager->getRepository(Product::class)->findOneBy(['uuid' => $productUuid]);
$productDoc = $this->documentManager->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)->findOneBy(['uid' => $product->getUID()]);
$productDoc = $this->documentManager
->getRepository(\PSC\Shop\EntityBundle\Document\Product::class)
->findOneBy(['uid' => $product->getUID()]);
/** @var Setting $settings */
$settings = $this->serializer->deserialize($productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}', Setting::class, 'json');
$settings = $this->serializer->deserialize(
$productDoc->getPluginSettingModule('collectlayouter', 'config') ?? '{}',
Setting::class,
'json',
);
}
require_once(__DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Item.php');
require_once(__DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Collection.php');
require_once(__DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Util.php');
require_once __DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Item.php';
require_once __DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Collection.php';
require_once __DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Util.php';
$basket = $_SESSION['Basket']['Articles'];
$newarray = $request->request->all();
if (isset($newarray["q"])) {
$q = "%" . $newarray["q"] . "%";
$s = $newarray["q"];
if (isset($newarray['q'])) {
$q = '%' . $newarray['q'] . '%';
$s = $newarray['q'];
$qb = $this->documentManager->getRepository(PSCContact::class)->createQueryBuilder('contact');
$qb->addOr($qb->expr()->field('custom1')->equals(new Regex($s, 'i')));
@ -457,57 +466,138 @@ class UserController extends AbstractController
$ids = [];
foreach ($qb->getQuery()->execute() as $row) {
$ids[] = (int)$row->getUid();
$ids[] = (int) $row->getUid();
}
$contacts = [];
if ($productDoc) {
$accountMode = $productDoc->getPluginSettingModule('collectlayouter', 'uploadCollectLayouterAccountFilter');
$accountSelect = $productDoc->getPluginSettingModule('collectlayouter', 'uploadCollectLayouterOrdersAccount');
$accountMode = $productDoc->getPluginSettingModule(
'collectlayouter',
'uploadCollectLayouterAccountFilter',
);
$accountSelect = $productDoc->getPluginSettingModule(
'collectlayouter',
'uploadCollectLayouterOrdersAccount',
);
if ($accountMode == 1) {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->orderBy('contact.' . $orderBy, $sort)
->leftJoin('contact.shops', 'shop')
->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop')->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere('(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)')->setParameter('ids', $ids)->setParameter("q", $q)->getQuery()->execute();
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop',
)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere(
'(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)',
)
->setParameter('ids', $ids)
->setParameter('q', $q)
->getQuery()
->execute();
} elseif ($accountMode == 2) {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->orderBy('contact.' . $orderBy, $sort)
->leftJoin('contact.shops', 'shop')
->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account')->setParameter('account', $this->getUser()->getAccount())->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere('(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)')->setParameter('ids', $ids)->setParameter("q", $q)->getQuery()->execute();
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account',
)
->setParameter('account', $this->getUser()->getAccount())
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere(
'(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)',
)
->setParameter('ids', $ids)
->setParameter('q', $q)
->getQuery()
->execute();
} elseif ($accountMode == 3) {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->orderBy('contact.' . $orderBy, $sort)
->leftJoin('contact.shops', 'shop')
->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account')->setParameter('account', $accountSelect)->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere('(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)')->setParameter('ids', $ids)->setParameter("q", $q)->getQuery()->execute();
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account',
)
->setParameter('account', $accountSelect)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere(
'(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)',
)
->setParameter('ids', $ids)
->setParameter('q', $q)
->getQuery()
->execute();
} elseif ($accountMode == 4) {
$accounts = [];
$accounts[] = $accountSelect;
$accounts = $this->getAccountsForAccount($accounts, $accountSelect);
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->orderBy('contact.' . $orderBy, $sort)
->leftJoin('contact.shops', 'shop')
->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)')->setParameter('account', $accounts)->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere('(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)')->setParameter('ids', $ids)->setParameter("q", $q)->getQuery()->execute();
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)',
)
->setParameter('account', $accounts)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere(
'(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)',
)
->setParameter('ids', $ids)
->setParameter('q', $q)
->getQuery()
->execute();
} elseif ($accountMode == 5) {
$accounts = [];
$accounts[] = $this->getUser()->getAccount();
$accounts = $this->getAccountsForAccount($accounts, $this->getUser()->getAccount());
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->orderBy('contact.' . $orderBy, $sort)
->leftJoin('contact.shops', 'shop')
->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)')->setParameter('account', $accounts)->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere('(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)')->setParameter('ids', $ids)->setParameter("q", $q)->getQuery()->execute();
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)',
)
->setParameter('account', $accounts)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere(
'(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)',
)
->setParameter('ids', $ids)
->setParameter('q', $q)
->getQuery()
->execute();
}
} else {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->orderBy('contact.' . $orderBy, $sort)
->leftJoin('contact.shops', 'shop')
->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop')->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere('(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)')->setParameter('ids', $ids)->setParameter("q", $q)->getQuery()->execute();
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop',
)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->andwhere(
'(contact.uid in (:ids) or contact.firstname like :q or contact.lastname like :q or contact.username like :q or contact.company like :q or contact.street like :q or contact.houseNumber like :q or contact.city like :q or contact.zip like :q or CONCAT(contact.firstname, \' \', contact.lastname) like :q)',
)
->setParameter('ids', $ids)
->setParameter('q', $q)
->getQuery()
->execute();
}
$temp = [];
@ -519,40 +609,115 @@ class UserController extends AbstractController
}
}
return array(
return [
'contacts' => $temp,
'sort' => $sort == 'asc' ? 'desc' : 'asc',
'orderBy' => $orderBy,
'basket' => $basket,
'productUuid' => $productUuid,
'product' => $product,
'settings' => $settings
);
'settings' => $settings,
];
} else {
$contacts = [];
if ($productDoc) {
$accountMode = $productDoc->getPluginSettingModule('collectlayouter', 'uploadCollectLayouterAccountFilter');
$accountSelect = $productDoc->getPluginSettingModule('collectlayouter', 'uploadCollectLayouterOrdersAccount');
$accountMode = $productDoc->getPluginSettingModule(
'collectlayouter',
'uploadCollectLayouterAccountFilter',
);
$accountSelect = $productDoc->getPluginSettingModule(
'collectlayouter',
'uploadCollectLayouterOrdersAccount',
);
if ($accountMode == 1) {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')->leftJoin('contact.shops', 'shop')->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop')->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())->orderBy('contact.' . $orderBy, $sort)->getQuery()->execute();
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop',
)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->orderBy('contact.' . $orderBy, $sort)
->getQuery()
->execute();
} elseif ($accountMode == 2) {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')->leftJoin('contact.shops', 'shop')->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account')->setParameter('account', $this->getUser()->getAccount())->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())->orderBy('contact.' . $orderBy, $sort)->getQuery()->execute();
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account',
)
->setParameter('account', $this->getUser()->getAccount())
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->orderBy('contact.' . $orderBy, $sort)
->getQuery()
->execute();
} elseif ($accountMode == 3) {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')->leftJoin('contact.shops', 'shop')->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account')->setParameter('account', $accountSelect)->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())->orderBy('contact.' . $orderBy, $sort)->getQuery()->execute();
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account = :account',
)
->setParameter('account', $accountSelect)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->orderBy('contact.' . $orderBy, $sort)
->getQuery()
->execute();
} elseif ($accountMode == 4) {
$accounts = [];
$accounts[] = $accountSelect;
$accounts = $this->getAccountsForAccount($accounts, $accountSelect);
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')->leftJoin('contact.shops', 'shop')->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)')->setParameter('account', $accounts)->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())->orderBy('contact.' . $orderBy, $sort)->getQuery()->execute();
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)',
)
->setParameter('account', $accounts)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->orderBy('contact.' . $orderBy, $sort)
->getQuery()
->execute();
} elseif ($accountMode == 5) {
$accounts = [];
$accounts[] = $this->getUser()->getAccount();
$accounts = $this->getAccountsForAccount($accounts, $this->getUser()->getAccount());
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')->leftJoin('contact.shops', 'shop')->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)')->setParameter('account', $accounts)->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())->orderBy('contact.' . $orderBy, $sort)->getQuery()->execute();
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop AND contact.account in (:account)',
)
->setParameter('account', $accounts)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->orderBy('contact.' . $orderBy, $sort)
->getQuery()
->execute();
}
} else {
$contacts = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->createQueryBuilder('contact')->leftJoin('contact.shops', 'shop')->where('contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop')->setParameter('sysadmin_email', "sysadmin@printshopcreator.de")->setParameter('shop', $this->shopService->getShopByDomain()->getId())->orderBy('contact.' . $orderBy, $sort)->getQuery()->execute();
$contacts = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->createQueryBuilder('contact')
->leftJoin('contact.shops', 'shop')
->where(
'contact.username != :sysadmin_email AND contact.enable = 1 AND contact.uid != 1 AND shop.uid = :shop',
)
->setParameter('sysadmin_email', 'sysadmin@printshopcreator.de')
->setParameter('shop', $this->shopService->getShopByDomain()->getId())
->orderBy('contact.' . $orderBy, $sort)
->getQuery()
->execute();
}
$temp = [];
foreach ($contacts as $contact) {
@ -563,35 +728,49 @@ class UserController extends AbstractController
}
}
return array(
return [
'contacts' => $temp,
'sort' => $sort == 'asc' ? 'desc' : 'asc',
'orderBy' => $orderBy,
'basket' => $basket,
'productUuid' => $productUuid,
'product' => $product,
'settings' => $settings
);
'settings' => $settings,
];
}
}
#[Route('/copy/{productUuid}/{contactUuid}', name: 'plugin_custom_psc_collectlayouter_user_copy')]
public function copy(EntityManagerInterface $entityManager, \PSC\Shop\ContactBundle\Service\Contact $contactService, string $contactUuid, string $productUuid = '')
{
$contact = $entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->findOneBy(array('uuid' => $contactUuid));
public function copy(
EntityManagerInterface $entityManager,
\PSC\Shop\ContactBundle\Service\Contact $contactService,
string $contactUuid,
string $productUuid = '',
) {
$contact = $entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->findOneBy(['uuid' => $contactUuid]);
$copyContact = $contactService->copy($contact);
if ($productUuid != "") {
return $this->redirectToRoute('plugin_custom_psc_collectlayouter_collect', ['productUuid' => $productUuid, 'contactUuid' => $copyContact->getUuid(), 'mode' => 2]);
if ($productUuid != '') {
return $this->redirectToRoute('plugin_custom_psc_collectlayouter_collect', [
'productUuid' => $productUuid,
'contactUuid' => $copyContact->getUuid(),
'mode' => 2,
]);
}
return $this->redirectToRoute('plugin_custom_psc_collectlayouter_user_edit', ['productUuid' => $productUuid, 'contactUuid' => $copyContact->getUuid()]);
return $this->redirectToRoute('plugin_custom_psc_collectlayouter_user_edit', [
'productUuid' => $productUuid,
'contactUuid' => $copyContact->getUuid(),
]);
}
#[Route('/lock/{productUuid}/{contactUuid}', name: 'plugin_custom_psc_collectlayouter_user_lock')]
public function lock(EntityManagerInterface $entityManager, string $contactUuid, string $productUuid = '')
{
$contact = $entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->findOneBy(array('uuid' => $contactUuid));
$contact = $entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->findOneBy(['uuid' => $contactUuid]);
$contact->setLocked(!$contact->isLocked());
$entityManager->persist($contact);
$entityManager->flush();
@ -603,7 +782,9 @@ class UserController extends AbstractController
public function disable(EntityManagerInterface $entityManager, string $contactUuid, string $productUuid = '')
{
/** @var Contact $contact */
$contact = $entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->findOneBy(array('uuid' => $contactUuid));
$contact = $entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->findOneBy(['uuid' => $contactUuid]);
$contact->setEnable(false);
$entityManager->persist($contact);
$entityManager->flush();
@ -615,23 +796,39 @@ class UserController extends AbstractController
public function vcardAction(EntityManagerInterface $entityManager, $contactUuid)
{
/** @var Contact $contact */
$contact = $entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Contact')->findOneBy(array('uuid' => $contactUuid));
$contact = $entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Contact')
->findOneBy(['uuid' => $contactUuid]);
$vcard = new VCard();
$vcard->addName($contact->getLastname(), $contact->getFirstname(), "", "", "");
$vcard->addName($contact->getLastname(), $contact->getFirstname(), '', '', '');
$vcard->addCompany($contact->getCompany());
$title = $contact->getPosition();
if ($contact->getAbteilung() != "") {
if ($contact->getAbteilung() != '') {
$title = $title . ', ' . $contact->getAbteilung();
}
if ($contact->getFunction() != "") {
if ($contact->getFunction() != '') {
$title = $title . ', ' . $contact->getFunction();
}
$vcard->addJobtitle($title);
$vcard->addEmail($contact->getUsername());
$vcard->addPhoneNumber('+'. $contact->getPhoneAreaCode() .' '. $contact->getPhonePrefix() .' '. $contact->getPhone(), 'voice,work,pref');
$vcard->addPhoneNumber('+'. $contact->getMobileAreaCode() .' '. $contact->getMobilePrefix() .' '. $contact->getMobile(), 'cell,work,pref');
$vcard->addAddress(null, null, $contact->getStreet() . ' ' . $contact->getHouseNumber(), $contact->getCity(), null, $contact->getZip(), $contact->getCountry());
$vcard->addPhoneNumber(
'+' . $contact->getPhoneAreaCode() . ' ' . $contact->getPhonePrefix() . ' ' . $contact->getPhone(),
'voice,work,pref',
);
$vcard->addPhoneNumber(
'+' . $contact->getMobileAreaCode() . ' ' . $contact->getMobilePrefix() . ' ' . $contact->getMobile(),
'cell,work,pref',
);
$vcard->addAddress(
null,
null,
$contact->getStreet() . ' ' . $contact->getHouseNumber(),
$contact->getCity(),
null,
$contact->getZip(),
$contact->getCountry(),
);
$vcard->addURL('https://' . $contact->getHomepage());
$vcard->download();
die();
@ -639,7 +836,9 @@ class UserController extends AbstractController
private function getAccountsForAccount(array $accounts, $accountSelect)
{
$accountsEntity = $this->entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Account')->findBy(array('parent' => $accountSelect));
$accountsEntity = $this->entityManager
->getRepository('PSC\Shop\EntityBundle\Entity\Account')
->findBy(['parent' => $accountSelect]);
foreach ($accountsEntity as $accountEntity) {
$accounts[] = $accountEntity->getId();
$accounts = $this->getAccountsForAccount($accounts, $accountEntity->getId());

View File

@ -0,0 +1,71 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Api;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use OpenApi\Attributes\Parameter;
use OpenApi\Attributes\Response;
use OpenApi\Attributes\Tag;
use Plugin\Custom\PSC\LaufkartenLayouter\Model\Setting;
use PSC\Shop\EntityBundle\Entity\Product;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Serializer\SerializerInterface;
class GetSettings
{
#[Response(response: 200, description: 'Settings loaded successfully')]
#[Response(response: 404, description: 'Product not found')]
#[Route('/settings/{productUUId}', name: 'plugin_custom_psc_laufkartenlayouter_get_settings', methods: ['GET'])]
#[Tag(name: 'Plugin/Custom/PSC/LaufkartenLayouter')]
#[Parameter(name: 'productUUId', in: 'path', required: true, description: 'Product UUID')]
public function getSettingsAction(
string $productUUId,
EntityManagerInterface $entityManager,
DocumentManager $documentManager,
SerializerInterface $serializer
): JsonResponse {
/** @var Product|null $product */
$product = $entityManager
->getRepository(Product::class)
->findOneBy(['uuid' => $productUUId]);
if (!$product) {
return new JsonResponse(['error' => 'Product not found'], JsonResponse::HTTP_NOT_FOUND);
}
/** @var \PSC\Shop\EntityBundle\Document\Product $productDoc */
$productDoc = $documentManager
->getRepository('PSC\\Shop\\EntityBundle\\Document\\Product')
->findOneBy(['uid' => (string) $product->getUid()]);
// Load existing settings or create defaults
$configData = $productDoc->getPluginSettingModule('laufkartenlayouter', 'config');
if ($configData) {
$setting = $serializer->deserialize(
json_encode($configData),
Setting::class,
'json'
);
} else {
// Return default settings
$setting = new Setting();
$tabPositions = [];
for ($i = 1; $i <= 10; $i++) {
$tabPosition = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\TabPosition();
$tabPosition->setTabNumber($i);
$tabPosition->setX(0);
$tabPosition->setY(0);
$tabPositions[] = $tabPosition;
}
$setting->setTabPositions($tabPositions);
}
// Serialize settings to JSON
$settingsJson = $serializer->serialize($setting, 'json');
return new JsonResponse(json_decode($settingsJson, true));
}
}

View File

@ -0,0 +1,256 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Api;
use Doctrine\ODM\MongoDB\DocumentManager;
use OpenApi\Attributes\Response;
use OpenApi\Attributes\Tag;
use Plugin\Custom\PSC\LaufkartenLayouter\Dto\Input;
use PSC\Shop\EntityBundle\Entity\Product;
use PSC\Shop\EntityBundle\Repository\ProductRepository;
use PSC\Shop\MediaBundle\Service\MediaManager;
use setasign\Fpdi\Tcpdf\Fpdi;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
class Preview
{
#[Response(response: 200, description: 'PDF preview generated successfully')]
#[Response(response: 400, description: 'Bad request')]
#[Route('/preview', name: 'plugin_custom_psc_laufkartenlayouter_preview', methods: ['POST'])]
#[Tag(name: 'Plugin/Custom/PSC/LaufkartenLayouter')]
public function previewAction(
#[MapRequestPayload] Input $data,
ProductRepository $productRepository,
DocumentManager $documentManager,
MediaManager $mediaManager,
): BinaryFileResponse|JsonResponse {
// TODO: Implement PDF generation with OCR numbers in colors
// For now, return a placeholder response
// Get files data
$files = $data->files;
/** @var Product $product */
$product = $productRepository->findOneBy(['uuid' => $data->productUUId]);
/** @var \PSC\Shop\EntityBundle\Document\Product $productDoc */
$productDoc = $documentManager
->getRepository('PSC\\Shop\\EntityBundle\\Document\\Product')
->findOneBy(['uid' => (string) $product->getUid()]);
// Load existing settings or create defaults
$configData = $productDoc->getPluginSettingModule('laufkartenlayouter', 'config');
$overlayPdf = 'inhalt.pdf';
$outPdf = 'final.pdf';
// Ziel-Seitenformat: A4 in mm (alternativ Custom unten)
// Overlay-Seite aus inhalt.pdf
$ovPageNo = 1;
// Position/Skalierung des Overlays (alles in mm; Y von oben!)
$ovX = 30;
$ovY = 60;
$ovW = 150; // Breite in mm
$ovH = 0; // 0 = proportional
// Zahl/Box darüber (mm; Y von oben!)
$number = '17';
$boxX = 30;
$boxY = 40;
$boxW = 20;
$boxH = 10;
$fontSize = 14; // Schriftgröße bleibt in pt
$pdf = new Fpdi($configData['orientation'], $configData['unit'], [$configData['width'], $configData['height']]);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$frontSide = true;
foreach ($data->files as $file) {
$media = $mediaManager->getModelByUuid($file['uuid']['$oid']);
$pdf->setSourceFile($media->getCompletePath());
if ($file['numPages'] > 1) {
$tpl = $pdf->importPage(1);
$pdf->AddPage($configData['orientation'], [$configData['width'], $configData['height']]);
$pdf->useTemplate(
$tpl,
$configData['contentAreaLeft'],
$configData['contentAreaTop'],
$configData['contentAreaWidth'],
$configData['contentAreaHeight'],
false,
);
$pdf->SetFont('helvetica', '', $fontSize);
$pdf->SetTextColor(0, 0, 0);
if ($file['color'] == 'red') {
$pdf->SetTextColor(255, 0, 0);
}
if ($file['color'] == 'green') {
$pdf->SetTextColor(0, 255, 0);
}
if ($file['color'] == 'blue') {
$pdf->SetTextColor(0, 0, 255);
}
if ($file['color'] == 'yellow') {
$pdf->SetTextColor(255, 255, 0);
}
$tab = array_filter($configData['tabPositions'], function ($item) use ($file) {
return $item['tabNumber'] == $file['tabNumber'] ? $item : null;
})[0];
$pdf->MultiCell(
$tab['width'],
$tab['height'],
$file['ocrNumber'],
0,
'C',
false,
1,
$tab['x'],
$tab['y'],
true,
0,
false,
true,
$tab['height'],
'M',
);
$tpl = $pdf->importPage(2);
$pdf->AddPage($configData['orientation'], [$configData['width'], $configData['height']]);
$pdf->useTemplate(
$tpl,
$configData['contentAreaLeft'],
$configData['contentAreaTop'],
$configData['contentAreaWidth'],
$configData['contentAreaHeight'],
false,
);
$pdf->SetFont('helvetica', '', $fontSize);
$pdf->SetTextColor(0, 0, 0);
if ($file['color'] == 'red') {
$pdf->SetTextColor(255, 0, 0);
}
if ($file['color'] == 'green') {
$pdf->SetTextColor(0, 255, 0);
}
if ($file['color'] == 'blue') {
$pdf->SetTextColor(0, 0, 255);
}
if ($file['color'] == 'yellow') {
$pdf->SetTextColor(255, 255, 0);
}
$pdf->MultiCell(
$tab['width'],
$tab['height'],
$file['ocrNumber'],
0,
'C',
false,
1,
($configData['width'] - $tab['width']) - $tab['x'],
$tab['y'],
true,
0,
false,
true,
$tab['height'],
'M',
);
} else {
$tpl = $pdf->importPage(1);
$pdf->AddPage($configData['orientation'], [$configData['width'], $configData['height']]);
$pdf->useTemplate(
$tpl,
$configData['contentAreaLeft'],
$configData['contentAreaTop'],
$configData['contentAreaWidth'],
$configData['contentAreaHeight'],
false,
);
$pdf->SetFont('helvetica', '', $fontSize);
$pdf->SetTextColor(0, 0, 0);
if ($file['color'] == 'red') {
$pdf->SetTextColor(255, 0, 0);
}
if ($file['color'] == 'green') {
$pdf->SetTextColor(0, 255, 0);
}
if ($file['color'] == 'blue') {
$pdf->SetTextColor(0, 0, 255);
}
if ($file['color'] == 'yellow') {
$pdf->SetTextColor(255, 255, 0);
}
if ($frontSide) {
$tab = array_filter($configData['tabPositions'], function ($item) use ($file) {
return $item['tabNumber'] == $file['tabNumber'] ? $item : null;
})[0];
$pdf->MultiCell(
$tab['width'],
$tab['height'],
$file['ocrNumber'],
0,
'C',
false,
1,
$tab['x'],
$tab['y'],
true,
0,
false,
true,
$tab['height'],
'M',
);
$frontSide = false;
} else {
$tab = array_filter($configData['tabPositions'], function ($item) use ($file) {
return $item['tabNumber'] == $file['tabNumber'] ? $item : null;
})[0];
$pdf->MultiCell(
$tab['width'],
$tab['height'],
$file['ocrNumber'],
0,
'C',
false,
1,
($configData['width'] - $tab['width']) - $tab['x'],
$tab['y'],
true,
0,
false,
true,
$tab['height'],
'M',
);
$frontSide = true;
}
}
}
$tmp = tempnam(sys_get_temp_dir(), 'pdf_') . '.pdf';
$pdf->Output($tmp, 'F');
$response = new BinaryFileResponse($tmp);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE, 'demo.pdf');
$response->headers->set('Content-Type', 'application/pdf');
$response->deleteFileAfterSend(true);
return $response;
if (empty($files)) {
return new JsonResponse(['error' => 'No files provided'], 400);
}
return new JsonResponse([
'success' => true,
'message' => 'Preview generation not yet implemented',
'filesCount' => count($files),
'layouterUUId' => $data->layouterUUId,
'productUUId' => $data->productUUId,
]);
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Controller\Backend;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use Plugin\Custom\PSC\LaufkartenLayouter\Form\TabPositions;
use Plugin\Custom\PSC\LaufkartenLayouter\Model\Setting;
use PSC\Shop\EntityBundle\Entity\Product;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Serializer\SerializerInterface;
#[Route('/index')]
#[IsGranted('ROLE_ADMIN')]
class IndexController extends AbstractController
{
#[Template('@PluginCustomPSCLaufkartenLayouter/backend/index/index.html.twig')]
#[Route('/{productUUId}', name: 'psc_plugin_custom_laufkartenlayouter_backend_index')]
public function indexAction(
Request $request,
EntityManagerInterface $entityManager,
DocumentManager $documentManager,
SerializerInterface $serializer,
$productUUId,
) {
/** @var Product $product */
$product = $entityManager
->getRepository('PSC\\Shop\\EntityBundle\\Entity\\Product')
->findOneBy(['uuid' => $productUUId]);
/** @var \PSC\Shop\EntityBundle\Document\Product $productDoc */
$productDoc = $documentManager
->getRepository('PSC\\Shop\\EntityBundle\\Document\\Product')
->findOneBy(['uid' => (string) $product->getUid()]);
// Load existing settings or create defaults
$configData = $productDoc->getPluginSettingModule('laufkartenlayouter', 'config');
if ($configData) {
$setting = $serializer->deserialize(json_encode($configData), Setting::class, 'json');
} else {
$setting = new Setting();
// Initialize default tab positions
$tabPositions = [];
for ($i = 1; $i <= 10; $i++) {
$tabPosition = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\TabPosition();
$tabPosition->setTabNumber($i);
$tabPosition->setX(0.0);
$tabPosition->setY(0.0);
$tabPosition->setWidth(0.0);
$tabPosition->setHeight(0.0);
$tabPositions[] = $tabPosition;
}
$setting->setTabPositions($tabPositions);
}
// Create tab positions form
$tabPositionsForm = $this->createForm(TabPositions::class, $setting);
$tabPositionsForm->handleRequest($request);
if ($tabPositionsForm->isSubmitted() && $tabPositionsForm->isValid()) {
// Save settings to MongoDB
$configArray = json_decode($serializer->serialize($setting, 'json'), true);
$productDoc->setPluginSettingModule('laufkartenlayouter', 'config', $configArray);
$documentManager->flush();
$this->addFlash('success', 'Einstellungen wurden gespeichert.');
return $this->redirectToRoute('psc_plugin_custom_laufkartenlayouter_backend_index', [
'productUUId' => $productUUId,
]);
}
return [
'product' => $product,
'tabPositionsForm' => $tabPositionsForm->createView(),
'setting' => $setting,
];
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Controller;
namespace Plugin\Custom\PSC\LaufkartenLayouter\Controller\Frontend;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
@ -13,7 +13,7 @@ use Symfony\Component\Routing\Attribute\Route;
#[Route('/designer')]
class DesignerController extends AbstractController
{
#[Template('@PluginCustomPSCLaufkartenLayouter/designer/start.html.twig')]
#[Template('@PluginCustomPSCLaufkartenLayouter/frontend/designer/start.html.twig')]
#[Route('/start/{productUUId}/{layouterUUId}', name: 'psc_plugin_laufkartenlayouter_start')]
public function startAction(
Request $request,
@ -36,6 +36,12 @@ class DesignerController extends AbstractController
->getRepository('PSC\Shop\EntityBundle\Document\Product')
->findOneBy(['uid' => (string) $product->getUid()]);
return ['product' => $product, 'layouterUUId' => $layouterUUId];
$isAdmin = $this->isGranted('ROLE_ADMIN');
return [
'product' => $product,
'layouterUUId' => $layouterUUId,
'isAdmin' => $isAdmin,
];
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TabPosition extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('tabNumber', IntegerType::class, [
'label' => 'Tab Number',
'attr' => ['readonly' => true],
])
->add('x', NumberType::class, [
'label' => 'X Position',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('y', NumberType::class, [
'label' => 'Y Position',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('width', NumberType::class, [
'label' => 'Width',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('height', NumberType::class, [
'label' => 'Height',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => \Plugin\Custom\PSC\LaufkartenLayouter\Model\TabPosition::class,
]);
}
}

View File

@ -0,0 +1,113 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Form;
use Plugin\Custom\PSC\LaufkartenLayouter\Model\Setting;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class TabPositions extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('orientation', ChoiceType::class, [
'label' => 'Orientation',
'choices' => [
'Portrait' => 'p',
'Landscape' => 'l',
],
])
->add('unit', ChoiceType::class, [
'label' => 'Unit',
'choices' => [
'Millimeter' => 'mm',
'Centimeter' => 'cm',
'Inch' => 'in',
],
])
->add('tabs', IntegerType::class, [
'label' => 'Number of Tabs',
'attr' => ['min' => 1, 'max' => 20],
])
->add('width', NumberType::class, [
'label' => 'Width',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('height', NumberType::class, [
'label' => 'Height',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('trimLeft', NumberType::class, [
'label' => 'Trim Left',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('trimRight', NumberType::class, [
'label' => 'Trim Right',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('trimTop', NumberType::class, [
'label' => 'Trim Top',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('trimBottom', NumberType::class, [
'label' => 'Trim Bottom',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('contentAreaLeft', NumberType::class, [
'label' => 'Content Area Left',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('contentAreaTop', NumberType::class, [
'label' => 'Content Area Top',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('contentAreaWidth', NumberType::class, [
'label' => 'Content Area Width',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('contentAreaHeight', NumberType::class, [
'label' => 'Content Area Height',
'scale' => 1,
'html5' => true,
'attr' => ['step' => '0.1'],
])
->add('tabPositions', CollectionType::class, [
'entry_type' => TabPosition::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'Tab Positions',
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Setting::class,
]);
}
}

View File

@ -0,0 +1,178 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Model;
class Setting
{
private string $orientation = 'p';
private string $unit = 'mm';
private int $tabs = 10;
private float $width = 320.0;
private float $height = 225.0;
private float $trimLeft = 5.0;
private float $trimRight = 5.0;
private float $trimTop = 5.0;
private float $trimBottom = 5.0;
private float $contentAreaLeft = 5.0;
private float $contentAreaTop = 5.0;
private float $contentAreaWidth = 310.0;
private float $contentAreaHeight = 215.0;
/**
* @var TabPosition[]
*/
private array $tabPositions = [];
public function getOrientation(): string
{
return $this->orientation;
}
public function setOrientation(string $orientation): self
{
$this->orientation = $orientation;
return $this;
}
public function getUnit(): string
{
return $this->unit;
}
public function setUnit(string $unit): self
{
$this->unit = $unit;
return $this;
}
public function getTabs(): int
{
return $this->tabs;
}
public function setTabs(int $tabs): self
{
$this->tabs = $tabs;
return $this;
}
public function getWidth(): float
{
return $this->width;
}
public function setWidth(float $width): self
{
$this->width = $width;
return $this;
}
public function getHeight(): float
{
return $this->height;
}
public function setHeight(float $height): self
{
$this->height = $height;
return $this;
}
public function getTrimLeft(): float
{
return $this->trimLeft;
}
public function setTrimLeft(float $trimLeft): self
{
$this->trimLeft = $trimLeft;
return $this;
}
public function getTrimRight(): float
{
return $this->trimRight;
}
public function setTrimRight(float $trimRight): self
{
$this->trimRight = $trimRight;
return $this;
}
public function getTrimTop(): float
{
return $this->trimTop;
}
public function setTrimTop(float $trimTop): self
{
$this->trimTop = $trimTop;
return $this;
}
public function getTrimBottom(): float
{
return $this->trimBottom;
}
public function setTrimBottom(float $trimBottom): self
{
$this->trimBottom = $trimBottom;
return $this;
}
public function getContentAreaLeft(): float
{
return $this->contentAreaLeft;
}
public function setContentAreaLeft(float $contentAreaLeft): self
{
$this->contentAreaLeft = $contentAreaLeft;
return $this;
}
public function getContentAreaTop(): float
{
return $this->contentAreaTop;
}
public function setContentAreaTop(float $contentAreaTop): self
{
$this->contentAreaTop = $contentAreaTop;
return $this;
}
public function getContentAreaWidth(): float
{
return $this->contentAreaWidth;
}
public function setContentAreaWidth(float $contentAreaWidth): self
{
$this->contentAreaWidth = $contentAreaWidth;
return $this;
}
public function getContentAreaHeight(): float
{
return $this->contentAreaHeight;
}
public function setContentAreaHeight(float $contentAreaHeight): self
{
$this->contentAreaHeight = $contentAreaHeight;
return $this;
}
public function getTabPositions(): array
{
return $this->tabPositions;
}
public function setTabPositions(array $tabPositions): self
{
$this->tabPositions = $tabPositions;
return $this;
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace Plugin\Custom\PSC\LaufkartenLayouter\Model;
class TabPosition
{
private int $tabNumber;
private float $x = 0.0;
private float $y = 0.0;
private float $width = 0.0;
private float $height = 0.0;
public function getTabNumber(): int
{
return $this->tabNumber;
}
public function setTabNumber(int $tabNumber): self
{
$this->tabNumber = $tabNumber;
return $this;
}
public function getX(): float
{
return $this->x;
}
public function setX(float $x): self
{
$this->x = $x;
return $this;
}
public function getY(): float
{
return $this->y;
}
public function setY(float $y): self
{
$this->y = $y;
return $this;
}
public function getWidth(): float
{
return $this->width;
}
public function setWidth(float $width): self
{
$this->width = $width;
return $this;
}
public function getHeight(): float
{
return $this->height;
}
public function setHeight(float $height): self
{
$this->height = $height;
return $this;
}
}

View File

@ -3,8 +3,13 @@ psc_shop_plugin_custom_laufkartenlayouter_api:
type: attribute
prefix: /api/plugin/custom/psc/laufkartenlayouter
psc_shop_plugin_custom_laufkartenlayouter_backend:
resource: "@PluginCustomPSCLaufkartenLayouter/Controller/Backend"
type: attribute
prefix: /plugin/custom/psc/laufkartenlayouter/backend
psc_shop_plugin_custom_laufkartenlayouter_frontend:
resource: "@PluginCustomPSCLaufkartenLayouter/Controller"
resource: "@PluginCustomPSCLaufkartenLayouter/Controller/Frontend"
type: attribute
prefix: /plugin/custom/psc/laufkartenlayouter/frontend

View File

@ -0,0 +1,230 @@
{% extends 'backend_plugin.html.twig' %}
{% block body %}
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<div class="row header">
<div class="col-md-8">
<h4>
<span id="productTitle">{{ product.title }}</span>
</h4>
</div>
<div class="col-md-4 text-end">
<a href="{{ path("backend_production_product_edit", {uuid: product.uuid}) }}"
class="btn btn-default btn-sm"><i class="fas fa-arrow-left"></i> Zurück</a>
</div>
</div>
</header>
<div class="container-fluid">
<main class="content">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active"
id="settings-tab"
data-bs-toggle="tab"
data-bs-target="#settings"
type="button"
role="tab"
aria-controls="settings"
aria-selected="true">Einstellungen</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link"
id="positions-tab"
data-bs-toggle="tab"
data-bs-target="#positions"
type="button"
role="tab"
aria-controls="positions"
aria-selected="false">Tab Positionen</button>
</li>
</ul>
{{ form_start(tabPositionsForm) }}
<div class="tab-content" id="myTabContent">
<div class="tab-pane active"
id="settings"
role="tabpanel"
aria-labelledby="settings-tab">
<div class="row">
<div class="col-6">
<div class="card d-flex">
<div class="card-header">Grundeinstellungen</div>
<div class="card-body">
<div class="row mb-3">
<label class="col-4 col-form-label">{{ form_label(tabPositionsForm.orientation) }}</label>
<div class="col-8">
{{ form_widget(tabPositionsForm.orientation, {'attr': {'class': 'form-select'}}) }}
</div>
</div>
<div class="row mb-3">
<label class="col-4 col-form-label">{{ form_label(tabPositionsForm.unit) }}</label>
<div class="col-8">
{{ form_widget(tabPositionsForm.unit, {'attr': {'class': 'form-select'}}) }}
</div>
</div>
<div class="row mb-3">
<label class="col-4 col-form-label">{{ form_label(tabPositionsForm.tabs) }}</label>
<div class="col-8">
{{ form_widget(tabPositionsForm.tabs, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
</div>
</div>
<div class="card d-flex mt-3">
<div class="card-header">Abmessungen</div>
<div class="card-body">
<div class="row mb-3">
<label class="col-4 col-form-label">Breite x Höhe</label>
<div class="col-8">
<div class="input-group">
{{ form_widget(tabPositionsForm.width, {'attr': {'class': 'form-control', 'placeholder': '320.0'}}) }}
<span class="input-group-text">X</span>
{{ form_widget(tabPositionsForm.height, {'attr': {'class': 'form-control', 'placeholder': '225.0'}}) }}
<span class="input-group-text">{{ setting.unit }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-6">
<div class="card d-flex">
<div class="card-header">Beschnitt</div>
<div class="card-body">
<div class="row mb-3">
<label class="col-4 col-form-label">Links / Rechts</label>
<div class="col-8">
<div class="input-group">
{{ form_widget(tabPositionsForm.trimLeft, {'attr': {'class': 'form-control', 'placeholder': '5.0'}}) }}
<span class="input-group-text">/</span>
{{ form_widget(tabPositionsForm.trimRight, {'attr': {'class': 'form-control', 'placeholder': '5.0'}}) }}
<span class="input-group-text">{{ setting.unit }}</span>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-4 col-form-label">Oben / Unten</label>
<div class="col-8">
<div class="input-group">
{{ form_widget(tabPositionsForm.trimTop, {'attr': {'class': 'form-control', 'placeholder': '5.0'}}) }}
<span class="input-group-text">/</span>
{{ form_widget(tabPositionsForm.trimBottom, {'attr': {'class': 'form-control', 'placeholder': '5.0'}}) }}
<span class="input-group-text">{{ setting.unit }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="card d-flex mt-3">
<div class="card-header">Inhaltsbereich</div>
<div class="card-body">
<div class="row mb-3">
<label class="col-4 col-form-label">Position (L / T)</label>
<div class="col-8">
<div class="input-group">
{{ form_widget(tabPositionsForm.contentAreaLeft, {'attr': {'class': 'form-control', 'placeholder': '5.0'}}) }}
<span class="input-group-text">/</span>
{{ form_widget(tabPositionsForm.contentAreaTop, {'attr': {'class': 'form-control', 'placeholder': '5.0'}}) }}
<span class="input-group-text">{{ setting.unit }}</span>
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-4 col-form-label">Breite x Höhe</label>
<div class="col-8">
<div class="input-group">
{{ form_widget(tabPositionsForm.contentAreaWidth, {'attr': {'class': 'form-control', 'placeholder': '310.0'}}) }}
<span class="input-group-text">X</span>
{{ form_widget(tabPositionsForm.contentAreaHeight, {'attr': {'class': 'form-control', 'placeholder': '215.0'}}) }}
<span class="input-group-text">{{ setting.unit }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-12 text-end">
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Einstellungen speichern
</button>
</div>
</div>
</div>
<div class="tab-pane"
id="positions"
role="tabpanel"
aria-labelledby="positions-tab">
<div class="row">
<div class="col-12">
<div class="card d-flex">
<div class="card-header">
Tab Positionen
<span class="badge bg-secondary float-end">{{ setting.tabs }} Tabs konfiguriert</span>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead class="table-dark">
<tr>
<th style="width: 10%">Tab Nr.</th>
<th style="width: 22.5%">X Position ({{ setting.unit }})</th>
<th style="width: 22.5%">Y Position ({{ setting.unit }})</th>
<th style="width: 22.5%">Breite ({{ setting.unit }})</th>
<th style="width: 22.5%">Höhe ({{ setting.unit }})</th>
</tr>
</thead>
<tbody>
{% for tabPosition in tabPositionsForm.tabPositions %}
<tr>
<td class="text-center align-middle">
<strong>{{ loop.index }}</strong>
{{ form_widget(tabPosition.tabNumber, {'attr': {'class': 'd-none'}}) }}
</td>
<td>
{{ form_widget(tabPosition.x, {'attr': {'class': 'form-control', 'placeholder': '0.0'}}) }}
</td>
<td>
{{ form_widget(tabPosition.y, {'attr': {'class': 'form-control', 'placeholder': '0.0'}}) }}
</td>
<td>
{{ form_widget(tabPosition.width, {'attr': {'class': 'form-control', 'placeholder': '0.0'}}) }}
</td>
<td>
{{ form_widget(tabPosition.height, {'attr': {'class': 'form-control', 'placeholder': '0.0'}}) }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-12 text-end">
<button type="submit" class="btn btn-success">
<i class="fas fa-save"></i> Positionen speichern
</button>
</div>
</div>
</div>
</div>
{{ form_end(tabPositionsForm) }}
</main>
</div>
{% endblock %}

View File

@ -11,6 +11,7 @@
</div>
</div>
</div>
{% if product %}<a class="btn btn-sm btn-primary" href="{{ path("psc_plugin_custom_laufkartenlayouter_backend_index", {productUUId: product.uuid}) }}">Template bearbeiten</a>{% endif %}
</div>
</div>
</div>

View File

@ -113,6 +113,10 @@
</div>
</div>
<!-- Invalid PDF Warning -->
<div id="invalidPDFWarning" class="hidden bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
</div>
<!-- PDF List Table -->
<div id="pdfTableContainer" class="bg-white rounded-lg shadow overflow-hidden hidden">
<div class="overflow-y-auto" style="max-height: 500px;">
@ -124,6 +128,7 @@
<th class="px-4 py-3 text-left text-xs font-medium uppercase tracking-wider">Dateiname</th>
<th class="px-4 py-3 text-center text-xs font-medium uppercase tracking-wider">Seiten</th>
<th class="px-4 py-3 text-center text-xs font-medium uppercase tracking-wider">2-Seitig</th>
<th class="px-4 py-3 text-center text-xs font-medium uppercase tracking-wider">Tab</th>
<th class="px-4 py-3 text-center text-xs font-medium uppercase tracking-wider">OCR Bereich</th>
<th class="px-4 py-3 text-center text-xs font-medium uppercase tracking-wider">Nummer (OCR)</th>
<th class="px-4 py-3 text-center text-xs font-medium uppercase tracking-wider">Farbe</th>
@ -156,7 +161,12 @@
<div id="finalSummary"></div>
<div class="mt-6 flex justify-between">
<button class="px-6 py-2 bg-gray-500 text-white rounded-lg hover:bg-gray-600" id="backToStep2">Zurück zu Schritt 2</button>
<button class="px-6 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600" id="finishBtn">Fertigstellen</button>
<div class="flex gap-2">
{% if isAdmin %}
<button class="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600" id="printPdfBtn">PrintPDF anzeigen</button>
{% endif %}
<button class="px-6 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600" id="finishBtn">Fertigstellen</button>
</div>
</div>
</div>
</div>
@ -214,10 +224,67 @@
let ocrPreviews = {};
const layouterUUId = '{{ layouterUUId }}';
const isEditMode = layouterUUId && layouterUUId !== '';
let settings = null; // Will be loaded from API
let maxTabs = 10; // Default, will be updated from settings
// Initialize PDF.js
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
// Load settings from API
async function loadSettings() {
try {
const response = await fetch('/apps/api/plugin/custom/psc/laufkartenlayouter/settings/{{product.uuid}}');
if (response.ok) {
settings = await response.json();
maxTabs = settings.tabs || 10;
console.log(`Loaded settings: ${maxTabs} tabs configured`);
} else {
console.warn('Could not load settings, using defaults');
}
} catch (error) {
console.error('Error loading settings:', error);
}
}
// Calculate tab number for a PDF based on pages
function calculateTabNumber(pdfIndex) {
let usedTabs = 0;
for (let i = 0; i < pdfIndex; i++) {
const pdf = pdfData[i];
const pages = pdf.numPages || 0;
if (pdf.isDuplex) {
// 2-seitig: Jede PDF belegt 1 Tab pro 2 Seiten
usedTabs += Math.ceil(pages / 2);
} else {
// 1-seitig: 2 PDFs teilen sich 1 Tab
// Wir zählen halbe Tabs und runden am Ende auf
usedTabs += pages * 0.5;
}
}
// Current PDF tab calculation
const currentPdf = pdfData[pdfIndex];
const currentPages = currentPdf.numPages || 0;
let currentTabsUsed;
if (currentPdf.isDuplex) {
currentTabsUsed = Math.ceil(currentPages / 2);
} else {
currentTabsUsed = currentPages * 0.5;
}
const startTab = (Math.floor(usedTabs) % maxTabs) + 1;
const endTab = (Math.floor(usedTabs + currentTabsUsed - 0.001) % maxTabs) + 1;
if (startTab === endTab) {
return `Tab ${startTab}`;
} else {
return `Tab ${startTab}-${endTab}`;
}
}
// Load existing layouter session if in edit mode
async function loadLayouterSession() {
if (!isEditMode) {
@ -268,18 +335,25 @@
document.getElementById('nextToStep2').disabled = false;
// Pre-populate pdfData with loaded metadata
pdfData = loadedFiles.map((fileData, index) => ({
index: index,
file: fileData.file,
fileName: fileData.fileName,
numPages: fileData.numPages,
isDuplex: fileData.isDuplex,
ocrNumber: fileData.ocrNumber,
color: fileData.color,
processed: fileData.ocrNumber ? true : false,
uploadedUuid: fileData.uuid,
isAlreadyUploaded: true // Mark as already uploaded
}));
pdfData = loadedFiles.map((fileData, index) => {
const numPages = fileData.numPages;
const isValid = numPages === 1 || numPages === 2;
return {
index: index,
file: fileData.file,
fileName: fileData.fileName,
numPages: numPages,
isDuplex: fileData.isDuplex,
ocrNumber: fileData.ocrNumber,
color: fileData.color,
tabNumber: fileData.tabNumber || '',
processed: fileData.ocrNumber ? true : false,
uploadedUuid: fileData.uuid,
isAlreadyUploaded: true, // Mark as already uploaded
isValid: isValid // Only 1 or 2 pages are valid
};
});
// Initialize placeholder thumbnails for loaded files
pdfData.forEach((pdf, index) => {
@ -296,9 +370,12 @@
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', () => {
document.addEventListener('DOMContentLoaded', async () => {
// Load settings first
await loadSettings();
if (isEditMode) {
loadLayouterSession();
await loadLayouterSession();
}
});
@ -308,12 +385,16 @@
pdfData.forEach((pdf, index) => {
const input = document.getElementById(`ocr-input-${index}`);
const colorSelect = document.getElementById(`color-select-${index}`);
const tabInput = document.getElementById(`tab-input-${index}`);
if (input) {
pdf.ocrNumber = input.value;
}
if (colorSelect) {
pdf.color = colorSelect.value;
}
if (tabInput) {
pdf.tabNumber = tabInput.value;
}
});
}
}
@ -415,6 +496,8 @@
const pdf = await pdfjsLib.getDocument(typedArray).promise;
const numPages = pdf.numPages;
const isValid = numPages === 1 || numPages === 2;
pdfData.push({
index: globalIndex,
file: file,
@ -424,7 +507,8 @@
ocrNumber: '',
color: 'black',
processed: false,
isAlreadyUploaded: false // Mark as NOT uploaded yet
isAlreadyUploaded: false, // Mark as NOT uploaded yet
isValid: isValid // Only 1 or 2 pages are valid
});
thumbnails[globalIndex] = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjYwIiBoZWlnaHQ9IjgwIiBmaWxsPSIjZTVlN2ViIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtc2l6ZT0iMTQiIGZpbGw9IiM5Y2EzYWYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGRvbWluYW50LWJhc2VsaW5lPSJtaWRkbGUiPlBERjwvdGV4dD48L3N2Zz4=';
@ -549,6 +633,8 @@
const pdf = await pdfjsLib.getDocument(typedArray).promise;
const numPages = pdf.numPages;
const isValid = numPages === 1 || numPages === 2;
pdfData.push({
index: i,
file: file,
@ -558,7 +644,8 @@
ocrNumber: '',
color: 'black',
processed: false,
isAlreadyUploaded: false // New files need to be uploaded
isAlreadyUploaded: false, // New files need to be uploaded
isValid: isValid // Only 1 or 2 pages are valid
});
// Use placeholder thumbnail initially
@ -645,10 +732,37 @@
const tbody = document.getElementById('pdfInfoTableBody');
tbody.innerHTML = '';
// Check if there are any invalid PDFs
const invalidPDFs = pdfData.filter(pdf => !pdf.isValid);
const warningMessage = document.getElementById('invalidPDFWarning');
if (invalidPDFs.length > 0) {
warningMessage.classList.remove('hidden');
const fileNames = invalidPDFs.map(pdf => pdf.fileName).join(', ');
warningMessage.innerHTML = `
<div class="flex items-center space-x-2">
<svg class="h-5 w-5 text-red-500" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
</svg>
<span><strong>Warnung:</strong> ${invalidPDFs.length} PDF(s) sind ungültig und können nicht verarbeitet werden. Nur PDFs mit 1 oder 2 Seiten werden akzeptiert.</span>
</div>
`;
} else {
warningMessage.classList.add('hidden');
}
pdfData.forEach((pdf, index) => {
const row = tbody.insertRow();
const isActive = index === currentFileIndex;
row.className = `cursor-pointer hover:bg-blue-50 ${isActive ? 'bg-blue-100 font-semibold' : ''}`;
const isInvalid = !pdf.isValid;
// Add red styling for invalid PDFs
let rowClass = `cursor-pointer hover:bg-blue-50 ${isActive ? 'bg-blue-100 font-semibold' : ''}`;
if (isInvalid) {
rowClass = `cursor-pointer bg-red-50 border-l-4 border-red-500 ${isActive ? 'bg-red-100 font-semibold' : ''}`;
}
row.className = rowClass;
row.onclick = (e) => {
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'BUTTON') {
loadPDFInfo(index);
@ -658,6 +772,12 @@
? `<img src="${ocrPreviews[index]}" class="h-12 w-auto border border-gray-300 rounded" style="image-rendering: pixelated;" />`
: '<span class="text-gray-400 text-xs">-</span>';
const tabInfo = calculateTabNumber(index);
const currentTabNumber = pdf.tabNumber || tabInfo.replace('Tab ', '');
const pageCountClass = isInvalid ? 'text-red-600 font-bold' : '';
const fileNameClass = isInvalid ? 'text-red-600' : '';
row.innerHTML = `
<td class="px-4 py-3 whitespace-nowrap text-sm">${index + 1}</td>
<td class="px-4 py-3 whitespace-nowrap" onclick="event.stopPropagation(); openPreviewForPDF(${index})">
@ -668,9 +788,17 @@
</svg>
</div>
</td>
<td class="px-4 py-3 text-sm">${pdf.fileName}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-center">${pdf.numPages}</td>
<td class="px-4 py-3 text-sm ${fileNameClass}">${pdf.fileName}${isInvalid ? ' <span class="text-xs">(Ungültig)</span>' : ''}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-center ${pageCountClass}">${pdf.numPages}${isInvalid ? ' <span class="text-xs">✗</span>' : ''}</td>
<td class="px-4 py-3 whitespace-nowrap text-sm text-center">${pdf.isDuplex ? 'Ja' : 'Nein'}</td>
<td class="px-4 py-3 whitespace-nowrap text-center" onclick="event.stopPropagation()">
<input type="text" class="w-24 px-2 py-1 text-center border border-gray-300 rounded focus:outline-none focus:border-blue-500 font-semibold text-blue-600"
id="tab-input-${index}"
value="${currentTabNumber}"
placeholder="${tabInfo}"
title="Berechneter Wert: ${tabInfo}"
onchange="updateTabNumber(${index}, this.value)" />
</td>
<td class="px-4 py-3 whitespace-nowrap text-center">
${ocrPreviewHtml}
</td>
@ -718,6 +846,12 @@
}
}
// Update tab number from manual input
function updateTabNumber(index, value) {
pdfData[index].tabNumber = value;
console.log(`PDF ${index}: Tab = ${value}`);
}
// Update color selection
function updateColor(index, color) {
pdfData[index].color = color;
@ -1030,19 +1164,30 @@
}
}
// Auto-process all PDFs
// Auto-process all PDFs (only valid ones)
async function autoProcessAll() {
// Filter only valid PDFs
const validPdfs = pdfData.filter(p => p.isValid);
if (validPdfs.length === 0) {
alert('Es gibt keine gültigen PDFs zur Verarbeitung.');
return;
}
document.getElementById('autoProcessAll').disabled = true;
for (let i = 0; i < pdfData.length; i++) {
if (!pdfData[i].processed) {
// Only process valid PDFs
if (pdfData[i].isValid && !pdfData[i].processed) {
await processOCR(i);
await new Promise(resolve => setTimeout(resolve, 500)); // Small delay between PDFs
}
}
document.getElementById('autoProcessAll').disabled = false;
alert('Alle PDFs wurden verarbeitet!');
const processedCount = validPdfs.filter(p => p.processed).length;
alert(`${processedCount} von ${validPdfs.length} gültigen PDFs wurden verarbeitet!`);
}
// Step navigation buttons
@ -1052,6 +1197,123 @@
document.getElementById('backToStep2').addEventListener('click', () => goToStep(2));
document.getElementById('autoProcessAll').addEventListener('click', () => autoProcessAll());
// PrintPDF button (only for admins)
const printPdfBtn = document.getElementById('printPdfBtn');
if (printPdfBtn) {
printPdfBtn.addEventListener('click', async () => {
// Filter only valid PDFs (1 or 2 pages)
const validPdfs = pdfData.filter(p => p.isValid);
const invalidPdfs = pdfData.filter(p => !p.isValid);
if (validPdfs.length === 0) {
alert('Es gibt keine gültigen PDFs zur Verarbeitung. Bitte laden Sie PDFs mit 1 oder 2 Seiten hoch.');
return;
}
if (invalidPdfs.length > 0) {
const confirmMsg = `${invalidPdfs.length} ungültige PDF(s) werden ausgeschlossen.\nNur ${validPdfs.length} gültige PDF(s) werden für den Preview verwendet.\n\nMöchten Sie fortfahren?`;
if (!confirm(confirmMsg)) {
return;
}
}
// Collect all OCR numbers and color selections from input fields (only for valid PDFs)
validPdfs.forEach((pdf) => {
const input = document.getElementById(`ocr-input-${pdf.index}`);
const colorSelect = document.getElementById(`color-select-${pdf.index}`);
if (input) {
pdf.ocrNumber = input.value;
}
if (colorSelect) {
pdf.color = colorSelect.value;
}
});
console.log('Generating PrintPDF preview...');
console.log('PDF Data (valid PDFs only):', validPdfs);
const originalText = printPdfBtn.textContent;
printPdfBtn.disabled = true;
printPdfBtn.textContent = 'Generiere Preview...';
try {
// Step 1: Upload all valid PDFs if not already uploaded
const uploadedUUIDs = [];
for (let i = 0; i < validPdfs.length; i++) {
let uploadUuid;
if (validPdfs[i].isAlreadyUploaded && validPdfs[i].uploadedUuid) {
console.log(`Using existing upload for ${validPdfs[i].fileName}`);
uploadUuid = validPdfs[i].uploadedUuid;
} else {
printPdfBtn.textContent = `Uploading... (${i + 1}/${validPdfs.length})`;
const uploadResult = await uploadSinglePDF(validPdfs[i], i);
uploadUuid = uploadResult.uuid;
validPdfs[i].uploadedUuid = uploadUuid;
validPdfs[i].isAlreadyUploaded = true;
console.log(`Uploaded ${validPdfs[i].fileName}: ${uploadUuid}`);
}
uploadedUUIDs.push({
uuid: uploadUuid,
fileName: validPdfs[i].fileName,
ocrNumber: validPdfs[i].ocrNumber,
color: validPdfs[i].color,
tabNumber: validPdfs[i].tabNumber,
numPages: validPdfs[i].numPages,
isDuplex: validPdfs[i].isDuplex
});
}
// Step 2: Call preview API
printPdfBtn.textContent = 'Generiere PDF...';
const previewResponse = await fetch('/apps/api/plugin/custom/psc/laufkartenlayouter/preview', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
layouterUUId: layouterUUId || 'preview',
productUUId: '{{product.uuid}}',
files: uploadedUUIDs
})
});
if (!previewResponse.ok) {
throw new Error(`Preview generation failed! status: ${previewResponse.status}`);
}
// Check if response is PDF or JSON
const contentType = previewResponse.headers.get('content-type');
if (contentType && contentType.includes('application/pdf')) {
// Download PDF
const blob = await previewResponse.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'laufkarten-preview.pdf';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
} else {
// Handle JSON response
const result = await previewResponse.json();
console.log('Preview Response:', result);
alert('Preview: ' + (result.message || 'PDF generiert'));
}
} catch (error) {
console.error('Error generating preview:', error);
alert('Fehler beim Generieren der Vorschau: ' + error.message);
} finally {
printPdfBtn.disabled = false;
printPdfBtn.textContent = originalText;
}
});
}
async function uploadSinglePDF(pdf, index) {
const formData = new FormData();
formData.append('file', pdf.file);
@ -1072,19 +1334,39 @@
}
document.getElementById('finishBtn').addEventListener('click', async () => {
// Collect all OCR numbers and color selections from input fields
pdfData.forEach((pdf, index) => {
const input = document.getElementById(`ocr-input-${index}`);
const colorSelect = document.getElementById(`color-select-${index}`);
// Filter only valid PDFs (1 or 2 pages)
const validPdfs = pdfData.filter(p => p.isValid);
const invalidPdfs = pdfData.filter(p => !p.isValid);
if (validPdfs.length === 0) {
alert('Es gibt keine gültigen PDFs zur Verarbeitung. Bitte laden Sie PDFs mit 1 oder 2 Seiten hoch.');
return;
}
if (invalidPdfs.length > 0) {
const confirmMsg = `${invalidPdfs.length} ungültige PDF(s) werden ausgeschlossen.\nNur ${validPdfs.length} gültige PDF(s) werden verarbeitet.\n\nMöchten Sie fortfahren?`;
if (!confirm(confirmMsg)) {
return;
}
}
// Collect all OCR numbers, color selections, and tab numbers from input fields (only for valid PDFs)
validPdfs.forEach((pdf) => {
const input = document.getElementById(`ocr-input-${pdf.index}`);
const colorSelect = document.getElementById(`color-select-${pdf.index}`);
const tabInput = document.getElementById(`tab-input-${pdf.index}`);
if (input) {
pdf.ocrNumber = input.value;
}
if (colorSelect) {
pdf.color = colorSelect.value;
}
if (tabInput) {
pdf.tabNumber = tabInput.value;
}
});
console.log('Final data:', pdfData);
console.log('Final data (valid PDFs only):', validPdfs);
// Disable button and show loading state
const finishBtn = document.getElementById('finishBtn');
@ -1092,34 +1374,35 @@
finishBtn.disabled = true;
try {
// Step 1: Upload all PDFs and collect UUIDs
finishBtn.textContent = `Uploading PDFs... (0/${pdfData.length})`;
// Step 1: Upload all valid PDFs and collect UUIDs
finishBtn.textContent = `Uploading PDFs... (0/${validPdfs.length})`;
const uploadedUUIDs = [];
for (let i = 0; i < pdfData.length; i++) {
for (let i = 0; i < validPdfs.length; i++) {
let uploadUuid;
// Check if this file was already uploaded (from loaded session or previous upload)
if (pdfData[i].isAlreadyUploaded && pdfData[i].uploadedUuid) {
console.log(`Skipping upload for ${pdfData[i].fileName} - already uploaded (UUID: ${pdfData[i].uploadedUuid})`);
uploadUuid = pdfData[i].uploadedUuid;
if (validPdfs[i].isAlreadyUploaded && validPdfs[i].uploadedUuid) {
console.log(`Skipping upload for ${validPdfs[i].fileName} - already uploaded (UUID: ${validPdfs[i].uploadedUuid})`);
uploadUuid = validPdfs[i].uploadedUuid;
} else {
// Upload new file
finishBtn.textContent = `Uploading PDFs... (${i + 1}/${pdfData.length})`;
const uploadResult = await uploadSinglePDF(pdfData[i], i);
finishBtn.textContent = `Uploading PDFs... (${i + 1}/${validPdfs.length})`;
const uploadResult = await uploadSinglePDF(validPdfs[i], i);
uploadUuid = uploadResult.uuid;
pdfData[i].uploadedUuid = uploadUuid;
pdfData[i].isAlreadyUploaded = true; // Mark as uploaded now
console.log(`Uploaded ${pdfData[i].fileName}: ${uploadUuid}`);
validPdfs[i].uploadedUuid = uploadUuid;
validPdfs[i].isAlreadyUploaded = true; // Mark as uploaded now
console.log(`Uploaded ${validPdfs[i].fileName}: ${uploadUuid}`);
}
uploadedUUIDs.push({
uuid: uploadUuid,
fileName: pdfData[i].fileName,
ocrNumber: pdfData[i].ocrNumber,
color: pdfData[i].color,
numPages: pdfData[i].numPages,
isDuplex: pdfData[i].isDuplex
fileName: validPdfs[i].fileName,
ocrNumber: validPdfs[i].ocrNumber,
color: validPdfs[i].color,
tabNumber: validPdfs[i].tabNumber,
numPages: validPdfs[i].numPages,
isDuplex: validPdfs[i].isDuplex
});
}
@ -1183,17 +1466,38 @@
function generateFinalSummary() {
const summary = document.getElementById('finalSummary');
const processedCount = pdfData.filter(p => p.processed).length;
const totalPageCount = pdfData.reduce((sum, p) => sum + p.numPages, 0);
const duplexCount = pdfData.filter(p => p.isDuplex).length;
let tableHtml = `
// Filter only valid PDFs (1 or 2 pages)
const validPdfs = pdfData.filter(p => p.isValid);
const invalidPdfs = pdfData.filter(p => !p.isValid);
const processedCount = validPdfs.filter(p => p.processed).length;
const totalPageCount = validPdfs.reduce((sum, p) => sum + p.numPages, 0);
const duplexCount = validPdfs.filter(p => p.isDuplex).length;
let tableHtml = '';
// Show warning if there are invalid PDFs
if (invalidPdfs.length > 0) {
tableHtml += `
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
<div class="flex items-center space-x-2">
<svg class="h-5 w-5 text-red-500" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
</svg>
<span><strong>Hinweis:</strong> ${invalidPdfs.length} ungültige PDF(s) wurden von der Verarbeitung ausgeschlossen (nur 1-2 Seiten erlaubt).</span>
</div>
</div>
`;
}
tableHtml += `
<div class="bg-white rounded-lg shadow p-6 mb-4">
<h5 class="text-lg font-semibold mb-4">Zusammenfassung</h5>
<h5 class="text-lg font-semibold mb-4">Zusammenfassung (Gültige PDFs)</h5>
<div class="grid grid-cols-4 gap-4">
<div class="text-center">
<p class="text-sm text-gray-600 mb-1">Anzahl PDFs:</p>
<h4 class="text-3xl font-bold text-blue-600">${pdfData.length}</h4>
<h4 class="text-3xl font-bold text-blue-600">${validPdfs.length}</h4>
</div>
<div class="text-center">
<p class="text-sm text-gray-600 mb-1">Gesamtseiten:</p>
@ -1225,7 +1529,7 @@
<tbody class="bg-white divide-y divide-gray-200">
`;
pdfData.forEach((pdf, index) => {
validPdfs.forEach((pdf, index) => {
const colorNames = {
'black': 'Schwarz',
'red': 'Rot',

View File

@ -8,44 +8,47 @@ use OpenApi\Attributes\Response;
use OpenApi\Attributes\Tag;
use Plugin\Custom\PSC\R2_Sendcloud\Dto\Input;
use PSC\Shop\EntityBundle\Document\Shop;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
class GetShippingMethods extends AbstractController
{
public function __construct()
{
}
public function __construct() {}
#[Route(path: '/shippings', methods: ['POST'], name: 'plugin_custom_psc_r2_sendcloud_api_shipping_all')]
#[ParamConverter('data', class: Input::class, converter: 'psc_rest.request_body')]
#[Tag('Plugin/Custom/PSC/Sendcloud')]
#[RequestBody(description: 'content',content: new JsonContent(ref: Input::class))]
#[RequestBody(description: 'content', content: new JsonContent(ref: Input::class))]
#[Response(response: 200, description: 'return shippings', content: new JsonContent(type: 'bool'))]
public function generatePreview(Input $data, \PSC\System\SettingsBundle\Service\Shop $shopService): JsonResponse {
if($data->weight == 0) {
return new JsonResponse(["success" => false, 'shippings' => []]);
public function generatePreview(
#[MapRequestPayload] Input $data,
\PSC\System\SettingsBundle\Service\Shop $shopService,
): JsonResponse {
if ($data->weight == 0) {
return new JsonResponse(['success' => false, 'shippings' => []]);
}
/** @var Shop $shop */
$shop = $shopService->getMongoSelectedShop();
$connection = new \Picqer\Carriers\SendCloud\Connection($shop->getPluginSettingModule('r2sendcloud', 'publicKey'), $shop->getPluginSettingModule('r2sendcloud', 'secretKey'));
$connection = new \Picqer\Carriers\SendCloud\Connection(
$shop->getPluginSettingModule('r2sendcloud', 'publicKey'),
$shop->getPluginSettingModule('r2sendcloud', 'secretKey'),
);
$sendcloudClient = new \Picqer\Carriers\SendCloud\SendCloud($connection);
$weight = $data->weight;
$shippingMethods = [];
foreach($sendcloudClient->shippingMethods()->all($data->getShippingAllRequestArray()) as $shippingMethod) {
$minWeight = ((float)$shippingMethod->min_weight)*1000;
$maxWeight = ((float)$shippingMethod->max_weight)*1000;
if($minWeight < $weight && $maxWeight > $weight) {
foreach ($sendcloudClient->shippingMethods()->all($data->getShippingAllRequestArray()) as $shippingMethod) {
$minWeight = ((float) $shippingMethod->min_weight) * 1000;
$maxWeight = ((float) $shippingMethod->max_weight) * 1000;
if ($minWeight < $weight && $maxWeight > $weight) {
$shippingMethods[$shippingMethod->id] = $shippingMethod->name;
}
}
return new JsonResponse(["success" => true, 'shippings' => $shippingMethods]);
return new JsonResponse(['success' => true, 'shippings' => $shippingMethods]);
}
}

View File

@ -4,35 +4,42 @@ namespace Plugin\Custom\PSC\Saxoprint_API_R1\ApiController;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ORM\EntityManagerInterface;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Annotation\Security;
use Nelmio\ApiDocBundle\Attribute\Model;
use Nelmio\ApiDocBundle\Attribute\Security;
use OpenApi\Attributes as OA;
use Plugin\Custom\PSC\Saxoprint_API_R1\Dto\Input;
use Plugin\Custom\PSC\Saxoprint_API_R1\Dto\Output;
use PSC\Shop\EntityBundle\Document\Product;
use PSC\Shop\EntityBundle\Repository\ProductRepository;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class ConfigController extends AbstractController
{
public function __construct(readonly private ProductRepository $productRepository, readonly private DocumentManager $documentManager, readonly private EntityManagerInterface $entityManager)
{
}
public function __construct(
private readonly ProductRepository $productRepository,
private readonly DocumentManager $documentManager,
private readonly EntityManagerInterface $entityManager,
) {}
#[OA\Response(response: 200, description: 'set config', content: new OA\JsonContent(ref: new Model(type: Output::class)))]
#[OA\Response(
response: 200,
description: 'set config',
content: new OA\JsonContent(ref: new Model(type: Output::class)),
)]
#[OA\Tag(name: 'Plugin/Custom/PSC/Saxoprint_API_R1')]
#[IsGranted('ROLE_SHOP')]
#[Security(name: 'Bearer')]
#[Security(name: 'ApiKeyAuth')]
#[Route(path: '/config/save/{uuid}', methods: ['PUT'])]
#[OA\RequestBody(description: 'config', content: new OA\JsonContent(ref: new Model(type: \Plugin\Custom\PSC\Saxoprint_API_R1\Dto\Input::class)))]
#[ParamConverter('data', class: '\Plugin\Custom\PSC\Saxoprint_API_R1\Dto\Input', converter: 'psc_rest.request_body')]
public function saveConfig(string $uuid, Input $data): JsonResponse
#[OA\RequestBody(
description: 'config',
content: new OA\JsonContent(ref: new Model(type: \Plugin\Custom\PSC\Saxoprint_API_R1\Dto\Input::class)),
)]
public function saveConfig(string $uuid, #[MapRequestPayload] Input $data): JsonResponse
{
/** @var \PSC\Shop\EntityBundle\Entity\Product $product */
$product = $this->productRepository->findOneBy(['uuid' => $uuid]);

View File

@ -9,11 +9,10 @@ use OpenApi\Annotations as OA;
use Plugin\Custom\PSC\TemplateprintLayouter\Dto\Backend\AttachLayouterToOrderPosition\Output;
use PSC\Shop\EntityBundle\Entity\Orderpos;
use PSC\Shop\EntityBundle\Repository\OrderposRepository;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class AttachLayoutToOrderPosition extends AbstractController
{
@ -53,4 +52,3 @@ class AttachLayoutToOrderPosition extends AbstractController
return $this->json($output);
}
}

View File

@ -10,12 +10,12 @@ use Plugin\Custom\PSC\TemplateprintLayouter\Dto\Basket\Add\Input;
use Plugin\Custom\PSC\TemplateprintLayouter\Dto\Basket\Add\Output;
use PSC\Shop\EntityBundle\Entity\Contact;
use Ramsey\Uuid\Uuid;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class Add extends AbstractController
{
@ -44,12 +44,7 @@ class Add extends AbstractController
* @OA\Tag(name="Plugin/Custom/psc/TemplateprintLayouter/Basket")
*/
#[Route(path: '/legacy/add', methods: ['POST'])]
#[ParamConverter(
'data',
class: '\Plugin\Custom\PSC\TemplateprintLayouter\Dto\Basket\Add\Input',
converter: 'psc_rest.request_body',
)]
public function add(Input $data): JsonResponse
public function add(#[MapRequestPayload] Input $data): JsonResponse
{
require_once __DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Item.php';
require_once __DIR__ . '/../../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Collection.php';
@ -144,4 +139,3 @@ class Add extends AbstractController
);
}
}

View File

@ -3,35 +3,41 @@
namespace Plugin\System\PSC\PSC_Reseller_Products\ApiController;
use Doctrine\ODM\MongoDB\DocumentManager;
use Nelmio\ApiDocBundle\Annotation\Model;
use Nelmio\ApiDocBundle\Annotation\Security;
use Nelmio\ApiDocBundle\Attribute\Model;
use Nelmio\ApiDocBundle\Attribute\Security;
use OpenApi\Attributes as OA;
use Plugin\System\PSC\PSC_Reseller_Products\Dto\Input;
use Plugin\System\PSC\PSC_Reseller_Products\Dto\Output;
use PSC\Shop\EntityBundle\Document\Product;
use PSC\Shop\EntityBundle\Repository\ProductRepository;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class ConfigController extends AbstractController
{
public function __construct(readonly private ProductRepository $productRepository, readonly private DocumentManager $documentManager)
{
}
public function __construct(
private readonly ProductRepository $productRepository,
private readonly DocumentManager $documentManager,
) {}
#[OA\Response(response: 200, description: 'set config', content: new OA\JsonContent(ref: new Model(type: Output::class)))]
#[OA\Response(
response: 200,
description: 'set config',
content: new OA\JsonContent(ref: new Model(type: Output::class)),
)]
#[OA\Tag(name: 'Plugin/System/PSC/PSC_Reseller_Products')]
#[IsGranted('ROLE_SHOP')]
#[Security(name: 'Bearer')]
#[Security(name: 'ApiKeyAuth')]
#[Route(path: '/config/save/{uuid}', methods: ['PUT'])]
#[OA\RequestBody(description: 'config',content: new OA\JsonContent(ref: new Model(type: \Plugin\System\PSC\PSC_Reseller_Products\Dto\Input::class)))]
#[ParamConverter('data', class: '\Plugin\System\PSC\PSC_Reseller_Products\Dto\Input', converter: 'psc_rest.request_body')]
public function saveConfig(string $uuid, Input $data): JsonResponse
#[OA\RequestBody(
description: 'config',
content: new OA\JsonContent(ref: new Model(type: \Plugin\System\PSC\PSC_Reseller_Products\Dto\Input::class)),
)]
public function saveConfig(string $uuid, #[MapRequestPayload] Input $data): JsonResponse
{
$product = $this->productRepository->findOneBy(['uuid' => $uuid]);
@ -47,3 +53,4 @@ class ConfigController extends AbstractController
return $this->json(new Output(true));
}
}

View File

@ -32,7 +32,6 @@ use PSC\Shop\ContactBundle\Transformer\Model\Contact as ContactTransformer;
use PSC\Shop\EntityBundle\Entity\Product;
use PSC\System\SettingsBundle\Service\Help;
use PSC\System\SettingsBundle\Service\PaperDB;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;

View File

@ -32,7 +32,6 @@ use PSC\Shop\ContactBundle\Transformer\Model\Contact as ContactTransformer;
use PSC\Shop\EntityBundle\Entity\Product;
use PSC\System\SettingsBundle\Service\Help;
use PSC\System\SettingsBundle\Service\PaperDB;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;

View File

@ -27,7 +27,6 @@ use PSC\Shop\ContactBundle\Model\Contact;
use PSC\Shop\ContactBundle\Transformer\Model\Contact as ContactTransformer;
use PSC\System\SettingsBundle\Service\Help;
use PSC\System\SettingsBundle\Service\PaperDB;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;

View File

@ -12,7 +12,6 @@ use OpenApi\Attributes\Tag;
use Plugin\System\PSC\XmlCalc\Model\Product;
use PSC\Component\ApiBundle\Dto\Error\NotFound;
use PSC\Shop\EntityBundle\Entity\Product as PSCProduct;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;

View File

@ -9,7 +9,6 @@ use OpenApi\Annotations as OA;
use Plugin\System\PSC\XmlCalc\Model\Shop;
use PSC\Component\ApiBundle\Dto\Error\NotFound;
use PSC\Shop\EntityBundle\Entity\Shop as PSCShop;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

View File

@ -10,7 +10,6 @@ use OpenApi\Attributes\Tag;
use Plugin\System\PSC\XmlCalc\Model\System;
use PSC\Component\ApiBundle\Dto\Error\NotFound;
use PSC\Shop\EntityBundle\Entity\Install;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

View File

@ -1318,10 +1318,18 @@ html {
max-width: 20em;
}
.max-w-md{
max-width: 28rem;
}
.max-w-xl{
max-width: 36rem;
}
.max-w-xs{
max-width: 20rem;
}
.flex-1{
flex: 1 1 0%;
}
@ -1755,9 +1763,9 @@ html {
border-color: rgb(250 204 21 / var(--tw-border-opacity));
}
.bg-blue-600{
.bg-blue-100{
--tw-bg-opacity: 1;
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
background-color: rgb(219 234 254 / var(--tw-bg-opacity));
}
.bg-blue-700{
@ -1794,11 +1802,6 @@ html {
background-color: rgb(220 252 231 / var(--tw-bg-opacity));
}
.bg-green-600{
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
}
.bg-indigo-500{
--tw-bg-opacity: 1;
background-color: rgb(99 102 241 / var(--tw-bg-opacity));
@ -1829,11 +1832,6 @@ html {
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
}
.bg-red-600{
--tw-bg-opacity: 1;
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
}
.bg-slate-100{
--tw-bg-opacity: 1;
background-color: rgb(241 245 249 / var(--tw-bg-opacity));
@ -2129,6 +2127,11 @@ html {
color: rgb(37 99 235 / var(--tw-text-opacity));
}
.text-blue-800{
--tw-text-opacity: 1;
color: rgb(30 64 175 / var(--tw-text-opacity));
}
.text-gray-400{
--tw-text-opacity: 1;
color: rgb(156 163 175 / var(--tw-text-opacity));
@ -2159,6 +2162,11 @@ html {
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.text-green-600{
--tw-text-opacity: 1;
color: rgb(22 163 74 / var(--tw-text-opacity));
}
.text-green-800{
--tw-text-opacity: 1;
color: rgb(22 101 52 / var(--tw-text-opacity));
@ -2696,11 +2704,6 @@ html {
background-color: rgb(107 114 128 / 0.05);
}
.hover\:bg-green-700:hover{
--tw-bg-opacity: 1;
background-color: rgb(21 128 61 / var(--tw-bg-opacity));
}
.hover\:bg-indigo-600:hover{
--tw-bg-opacity: 1;
background-color: rgb(79 70 229 / var(--tw-bg-opacity));
@ -2730,11 +2733,6 @@ html {
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
}
.hover\:bg-red-700:hover{
--tw-bg-opacity: 1;
background-color: rgb(185 28 28 / var(--tw-bg-opacity));
}
.hover\:bg-white:hover{
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));