diff --git a/.docker/images/nginx/conf.d/default.conf b/.docker/images/nginx/conf.d/default.conf index 2d62736b1..f87f8cc65 100644 --- a/.docker/images/nginx/conf.d/default.conf +++ b/.docker/images/nginx/conf.d/default.conf @@ -64,10 +64,10 @@ server { try_files $uri @sfFront; } - location /w2p/ { - proxy_pass http://tp:8080/w2p/; - proxy_temp_path /tmp/proxy; - } + # location /w2p/ { + # proxy_pass http://tp:8080/w2p/; + # proxy_temp_path /tmp/proxy; + #} location @sfFront { # Symfony if ($request_method = 'OPTIONS') { diff --git a/src/new/config/reference.php b/src/new/config/reference.php index a52f4b18b..848c5bec1 100644 --- a/src/new/config/reference.php +++ b/src/new/config/reference.php @@ -476,7 +476,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * datetime?: array{ * default_format?: scalar|Param|null, // Default: "Y-m-d\\TH:i:sP" * default_deserialization_formats?: list, - * default_timezone?: scalar|Param|null, // Default: "Europe/Berlin" + * default_timezone?: scalar|Param|null, // Default: "UTC" * cdata?: scalar|Param|null, // Default: true * }, * array_collection?: array{ @@ -576,7 +576,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * datetime?: array{ * default_format?: scalar|Param|null, // Default: "Y-m-d\\TH:i:sP" * default_deserialization_formats?: list, - * default_timezone?: scalar|Param|null, // Default: "Europe/Berlin" + * default_timezone?: scalar|Param|null, // Default: "UTC" * cdata?: scalar|Param|null, // Default: true * }, * array_collection?: array{ diff --git a/src/new/src/PSC/Backend/DashboardBundle/Resources/views/shop/my_editable_shops_tailwind.html.twig b/src/new/src/PSC/Backend/DashboardBundle/Resources/views/shop/my_editable_shops_tailwind.html.twig index 7cd1ba262..68e93738c 100644 --- a/src/new/src/PSC/Backend/DashboardBundle/Resources/views/shop/my_editable_shops_tailwind.html.twig +++ b/src/new/src/PSC/Backend/DashboardBundle/Resources/views/shop/my_editable_shops_tailwind.html.twig @@ -12,6 +12,7 @@ {% endif %} +{% if is_granted('ROLE_ADMIN') %} - +{% endif %} diff --git a/src/new/src/PSC/Component/ApiBundle/Api/Shop/Get.php b/src/new/src/PSC/Component/ApiBundle/Api/Shop/Get.php index d04feb993..74cc28ded 100755 --- a/src/new/src/PSC/Component/ApiBundle/Api/Shop/Get.php +++ b/src/new/src/PSC/Component/ApiBundle/Api/Shop/Get.php @@ -26,15 +26,15 @@ class Get extends AbstractController #[Response( response: 200, - description: 'my shops', + description: 'all shops', content: new JsonContent(ref: new Model(type: PSC\Component\ApiBundle\Dto\Shop\Shops\Output::class)), )] #[Tag(name: 'Shops')] #[Security(name: 'ApiKeyAuth')] #[Security(name: 'Bearer')] - #[Route(path: '/my_shops', methods: ['GET'])] + #[Route(path: '/shops', methods: ['GET'])] #[IsGranted('ROLE_SHOP')] - public function myShops(): JsonResponse + public function allShops(): JsonResponse { $shops = $this->entityManager->getRepository(\PSC\Shop\EntityBundle\Entity\Shop::class)->findAll(); @@ -49,15 +49,15 @@ class Get extends AbstractController #[Response( response: 200, - description: 'shops', + description: 'my shops', content: new JsonContent(ref: new Model(type: PSC\Component\ApiBundle\Dto\Shop\Shops\Output::class)), )] #[Tag(name: 'Shops')] #[Security(name: 'ApiKeyAuth')] #[Security(name: 'Bearer')] - #[Route(path: '/shops', methods: ['GET'])] + #[Route(path: '/my_shops', methods: ['GET'])] #[IsGranted('ROLE_SHOP')] - public function allAction(): JsonResponse + public function myAction(): JsonResponse { $shops = $this->shopContactRepository->myEditableShops($this->getUser()); diff --git a/src/new/src/PSC/Shop/BasketBundle/Api/Layouter/Save.php b/src/new/src/PSC/Shop/BasketBundle/Api/Layouter/Save.php index 940f38526..2471c20f7 100644 --- a/src/new/src/PSC/Shop/BasketBundle/Api/Layouter/Save.php +++ b/src/new/src/PSC/Shop/BasketBundle/Api/Layouter/Save.php @@ -60,10 +60,12 @@ class Save extends AbstractController $row->setLayouterModus($data->layouterModus); // TODO: Store uploadedFiles in session data $this->entityManager->persist($row); + $this->entityManager->flush(); return $this->json([ 'success' => true, 'layouterUUId' => $row->getUuid(), + 'layouterModus' => $row->getLayouterModus(), 'auth' => true, 'user' => $this->tokenStorage ->getToken() diff --git a/src/new/src/PSC/Shop/EntityBundle/Entity/LayouterSession.php b/src/new/src/PSC/Shop/EntityBundle/Entity/LayouterSession.php index 726e6dffa..9f617028b 100755 --- a/src/new/src/PSC/Shop/EntityBundle/Entity/LayouterSession.php +++ b/src/new/src/PSC/Shop/EntityBundle/Entity/LayouterSession.php @@ -23,7 +23,7 @@ class LayouterSession #[ORM\Column(name: 'title', type: 'string', length: 255, nullable: true)] protected string $title; - #[ORM\Column(name: 'org_article_id', type: 'integer')] + #[ORM\Column(name: 'org_article_id', type: 'string', length: 40, nullable: true)] protected string $productId; #[ORM\Column(name: 'contact_id', type: 'integer')] diff --git a/src/new/src/PSC/Shop/EntityBundle/Entity/Orderpos.php b/src/new/src/PSC/Shop/EntityBundle/Entity/Orderpos.php index 3a1102a2f..75d598d52 100755 --- a/src/new/src/PSC/Shop/EntityBundle/Entity/Orderpos.php +++ b/src/new/src/PSC/Shop/EntityBundle/Entity/Orderpos.php @@ -120,6 +120,9 @@ class Orderpos */ #[ORM\Column(name: 'external_approval_status', type: 'integer', nullable: true)] private ?int $externalApprovalStatus = null; + + #[ORM\Column(name: 'external_approval_message', type: 'text', nullable: true)] + private ?string $externalApprovalMessage = null; /** * @var Product */ @@ -219,17 +222,17 @@ class Orderpos /** * @var \DateTime */ - #[ORM\Column(name: 'delivery_date', type: 'date', nullable: false)] + #[ORM\Column(name: 'delivery_date', type: 'date', nullable: true)] private $deliveryDate; /** * @var integer */ - #[ORM\Column(name: 'maschine', type: 'integer', nullable: false)] + #[ORM\Column(name: 'maschine', type: 'integer', nullable: true)] private $maschine; /** * @var integer */ - #[ORM\Column(name: 'papier', type: 'integer', nullable: false)] + #[ORM\Column(name: 'papier', type: 'integer', nullable: true)] private $papier; /** * @var \DateTime @@ -1046,4 +1049,14 @@ class Orderpos { $this->externalApprovalStatus = $status; } + + public function getExternalApprovalMessage(): ?string + { + return $this->externalApprovalMessage; + } + + public function setExternalApprovalMessage(?string $message): void + { + $this->externalApprovalMessage = $message; + } } diff --git a/src/new/src/PSC/Shop/OrderBundle/Controller/ExternalApprovalController.php b/src/new/src/PSC/Shop/OrderBundle/Controller/ExternalApprovalController.php index bb3c01f0d..f40382c4e 100644 --- a/src/new/src/PSC/Shop/OrderBundle/Controller/ExternalApprovalController.php +++ b/src/new/src/PSC/Shop/OrderBundle/Controller/ExternalApprovalController.php @@ -2,9 +2,19 @@ namespace PSC\Shop\OrderBundle\Controller; +use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ORM\EntityManagerInterface; +use PSC\Library\Calc\Engine; +use PSC\Library\Calc\PaperContainer; +use PSC\Shop\EntityBundle\Document\Position; +use PSC\Shop\EntityBundle\Document\Product; use PSC\Shop\EntityBundle\Entity\Orderpos; use PSC\Shop\EntityBundle\Entity\Upload; +use PSC\Shop\OrderBundle\Model\Order\Position as AliasedPosition; +use PSC\Shop\OrderBundle\Transformer\Order\Position as PSCPosition; +use PSC\Shop\QueueBundle\Event\Position\ApprovalExternalAccept; +use PSC\Shop\QueueBundle\Event\Position\ApprovalExternalDeclined; +use PSC\System\SettingsBundle\Service\PaperDB; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Request; @@ -16,22 +26,49 @@ use Symfony\Component\Routing\Attribute\Route; class ExternalApprovalController extends AbstractController { #[Route(path: '/{uuid}', name: 'psc_shop_order_external_approval_show', methods: ['GET', 'POST'])] - public function show(string $uuid, Request $request, EntityManagerInterface $em): Response - { + public function show( + string $uuid, + Request $request, + EntityManagerInterface $em, + DocumentManager $dm, + PaperDB $paperService, + \PSC\Shop\QueueBundle\Service\Event\Manager $eventManagerService, + PSCPosition $positionTransformer, + ): Response { /** @var Orderpos|null $orderpos */ $orderpos = $em->getRepository(Orderpos::class)->findOneBy(['uuid' => $uuid]); + $orderposDoc = $dm->getRepository(Position::class)->findOneBy(['uid' => $orderpos->getUid()]); if (!$orderpos) { throw $this->createNotFoundException('Position nicht gefunden.'); } + $position = new AliasedPosition(); + $positionTransformer->fromDb($position, $orderpos, $orderposDoc); if ($request->isMethod('POST')) { $action = $request->request->get('action'); + $message = trim($request->request->get('message', '')); if ($action === 'approve') { $orderpos->setExternalApprovalStatus(1); + $notify = new ApprovalExternalAccept(); + $notify->setShop($orderpos->getOrder()->getShop()->getUID()); + $notify->setOrder($orderpos->getOrder()->getUuid()); + $notify->setPosition($orderpos->getUuid()); + $notify->setMessage($message); + $eventManagerService->addJob($notify); } elseif ($action === 'reject') { $orderpos->setExternalApprovalStatus(-1); + $notify = new ApprovalExternalDeclined(); + $notify->setShop($orderpos->getOrder()->getShop()->getUID()); + $notify->setOrder($orderpos->getOrder()->getUuid()); + $notify->setPosition($orderpos->getUuid()); + $notify->setMessage($message); + $eventManagerService->addJob($notify); + } + + if ($message !== '') { + $orderpos->setExternalApprovalMessage($message); } $em->flush(); @@ -39,8 +76,12 @@ class ExternalApprovalController extends AbstractController return $this->redirectToRoute('psc_shop_order_external_approval_show', ['uuid' => $uuid]); } + $articleCalc = $this->buildCalc($orderpos, $dm, $paperService); + return $this->render('@PSCShopOrder/external_approval/show.html.twig', [ 'orderpos' => $orderpos, + 'articleCalc' => $articleCalc, + 'position' => $position, ]); } @@ -72,4 +113,50 @@ class ExternalApprovalController extends AbstractController return $response; } + + private function buildCalc(Orderpos $orderpos, DocumentManager $dm, PaperDB $paperService): ?object + { + if (!$orderpos->hasCalcXml()) { + return null; + } + + $shop = $orderpos->getOrder()->getShop(); + + /** @var Position|null $objDoc */ + $objDoc = $dm->getRepository(Position::class)->findOneBy(['uid' => (string) $orderpos->getId()]); + + $paperContainer = new PaperContainer(); + $paperContainer->parse(simplexml_load_string($shop->getInstall()->getPaperContainer())); + + $engine = new Engine(); + $engine->setPaperRepository($paperService); + $engine->setPaperContainer($paperContainer); + + if ($shop->getInstall()->getCalcTemplates()) { + $engine->setTemplates('' . $shop->getInstall()->getCalcTemplates() . ''); + } + + $engine->loadString($orderpos->getCalcXml()); + $engine->setFormulas($shop->getFormel()); + $engine->setParameters($shop->getParameter()); + + if ($objDoc && isset($objDoc->getSpecialProductTypeObject()['params'])) { + $engine->setVariables($objDoc->getSpecialProductTypeObject()['params']); + $engine->setSavedCalcReferences($objDoc->getCalcReferences()); + if (isset($objDoc->getSpecialProductTypeObject()['kalk_artikel'])) { + $engine->setActiveArticle($objDoc->getSpecialProductTypeObject()['kalk_artikel']); + } + } elseif ($orderpos->getData()) { + $objPosition = unserialize($orderpos->getData()); + $engine->setVariables($objPosition->getOptions()); + if (isset($objPosition->getOptions()['kalk_artikel'])) { + $engine->setActiveArticle($objPosition->getOptions()['kalk_artikel']); + } + if ($objDoc && $objDoc->getXmlProduct() !== '') { + $engine->setActiveArticle($objDoc->getXmlProduct()); + } + } + + return $engine->getArticle(); + } } diff --git a/src/new/src/PSC/Shop/OrderBundle/Form/Backend/SearchType.php b/src/new/src/PSC/Shop/OrderBundle/Form/Backend/SearchType.php index 5bf86b5bd..19ae0c53b 100755 --- a/src/new/src/PSC/Shop/OrderBundle/Form/Backend/SearchType.php +++ b/src/new/src/PSC/Shop/OrderBundle/Form/Backend/SearchType.php @@ -13,9 +13,9 @@ namespace PSC\Shop\OrderBundle\Form\Backend; +use PSC\System\SettingsBundle\Service\Status; use Spiriit\Bundle\FormFilterBundle\Filter\Form\Type\TextFilterType; use Spiriit\Bundle\FormFilterBundle\Filter\Query\QueryInterface; -use PSC\System\SettingsBundle\Service\Status; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\FormBuilderInterface; @@ -26,8 +26,9 @@ use Symfony\Component\OptionsResolver\OptionsResolver; class SearchType extends AbstractType { protected $status = array(); -/** @var Session */ + /** @var Session */ protected $session; + public function __construct(RequestStack $requestStack, Status $status) { $this->status = $status->getOrderStatusAsArray(); @@ -37,51 +38,74 @@ class SearchType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $session = $this->session; - $builder - ->setMethod('POST') - ->add('term', TextFilterType::class, array( - 'data' => $session->get('order_search_term'), - 'apply_filter' => function (QueryInterface $filterQuery, $field, $values) use ($session) { - - $session->set('order_search_term', $values['value']); - if (empty($values['value'])) { - return null; - } - - $filterQuery->getQueryBuilder() - ->andWhere("( - orders.basketfield1 LIKE '%" . $values['value'] . "%' OR - orders.basketfield2 LIKE '%" . $values['value'] . "%' OR - contact.firstname LIKE '%" . $values['value'] . "%' OR - contact.lastname LIKE '%" . $values['value'] . "%' OR - contact.zip LIKE '%" . $values['value'] . "%' OR - contact.city LIKE '%" . $values['value'] . "%' OR - contact.houseNumber LIKE '%" . $values['value'] . "%' OR - contact.street LIKE '%" . $values['value'] . "%' OR - contact.uid = '" . $values['value'] . "' OR - orders.alias LIKE '%" . $values['value'] . "%') - "); - })) - ->add('status', ChoiceType::class, array( - 'choices' => $this->status, - 'required' => false, - 'multiple' => true, - //'expanded' => true, - 'label_attr' => ['class' => 'float-left'], - 'data' => $session->get('order_search_status'), - 'apply_filter' => function (QueryInterface $filterQuery, $field, $values) use ($session) { - - $session->set('order_search_status', $values['value']); - if (empty($values['value'])) { - return null; - } - - $filterQuery->getQueryBuilder() - ->andWhere(" - orders.status in (" . implode(",", $values['value']) . ") - "); + $builder->setMethod('POST')->add('term', TextFilterType::class, array( + 'data' => $session->get('order_search_term'), + 'apply_filter' => function (QueryInterface $filterQuery, $field, $values) use ($session) { + $session->set('order_search_term', $values['value']); + if (empty($values['value'])) { + return null; } - )); + + $filterQuery + ->getQueryBuilder() + ->andWhere( + "( + orders.basketfield1 LIKE '%" + . $values['value'] + . "%' OR + orders.basketfield2 LIKE '%" + . $values['value'] + . "%' OR + contact.firstname LIKE '%" + . $values['value'] + . "%' OR + contact.lastname LIKE '%" + . $values['value'] + . "%' OR + contact.zip LIKE '%" + . $values['value'] + . "%' OR + contact.city LIKE '%" + . $values['value'] + . "%' OR + contact.houseNumber LIKE '%" + . $values['value'] + . "%' OR + contact.street LIKE '%" + . $values['value'] + . "%' OR + contact.username LIKE '%" + . $values['value'] + . "%' OR + contact.uid = '" + . $values['value'] + . "' OR + orders.alias LIKE '%" + . $values['value'] + . "%') + ", + ); + }, + ))->add('status', ChoiceType::class, array( + 'choices' => $this->status, + 'required' => false, + 'multiple' => true, + //'expanded' => true, + 'label_attr' => ['class' => 'float-left'], + 'data' => $session->get('order_search_status'), + 'apply_filter' => function (QueryInterface $filterQuery, $field, $values) use ($session) { + $session->set('order_search_status', $values['value']); + if (empty($values['value'])) { + return null; + } + + $filterQuery->getQueryBuilder()->andWhere(' + orders.status in (' + . implode(',', $values['value']) + . ') + '); + }, + )); } public function getName() @@ -94,7 +118,7 @@ class SearchType extends AbstractType $resolver->setDefaults(array( 'translation_domain' => 'status', 'choice_translation_domain' => 'status', - 'csrf_protection' => false + 'csrf_protection' => false, )); } } diff --git a/src/new/src/PSC/Shop/OrderBundle/Resources/config/routing.yml b/src/new/src/PSC/Shop/OrderBundle/Resources/config/routing.yml index 2ac5aa327..df232d816 100755 --- a/src/new/src/PSC/Shop/OrderBundle/Resources/config/routing.yml +++ b/src/new/src/PSC/Shop/OrderBundle/Resources/config/routing.yml @@ -1,14 +1,12 @@ -psc_shop_order_backend: - resource: "@PSCShopOrderBundle/Controller/Backend" - type: attribute - prefix: /backend/order - psc_shop_order: resource: "@PSCShopOrderBundle/Controller" type: attribute prefix: /order - +psc_shop_order_backend: + resource: "@PSCShopOrderBundle/Controller/Backend" + type: attribute + prefix: /backend/order psc_shop_order_api: resource: "@PSCShopOrderBundle/Api" diff --git a/src/new/src/PSC/Shop/OrderBundle/Resources/views/external_approval/show.html.twig b/src/new/src/PSC/Shop/OrderBundle/Resources/views/external_approval/show.html.twig index 788fe3785..0da4583c9 100644 --- a/src/new/src/PSC/Shop/OrderBundle/Resources/views/external_approval/show.html.twig +++ b/src/new/src/PSC/Shop/OrderBundle/Resources/views/external_approval/show.html.twig @@ -61,41 +61,102 @@ {% endif %} + {# Auftragsdetails #} + {% set order = orderpos.order %} +
+
+

Auftragsdetails

+
+
+
+ Auftragsnummer + {{ order.alias }} +
+
+ Auftrag-ID + {{ order.uid }} +
+
+ Datum + {{ order.created|date('d.m.Y H:i') }} +
+
+ Kunde +
+

{{ order.contact.firstname }} {{ order.contact.lastname }}

+

{{ order.contact.username }}

+
+
+ {% set inv = order.invoiceAddress %} + {% if inv %} +
+ Rechnungsadresse +
+ {% if inv.company %}

{{ inv.company }}

{% endif %} +

{{ inv.firstname }} {{ inv.lastname }}

+

{{ inv.street }} {{ inv.houseNumber }}

+

{{ inv.zip }} {{ inv.city }}

+
+
+ {% endif %} + {% if order.basketfield1 or order.basketfield2 %} +
+ Kostenstelle + {{ order.basketfield1 }} {{ order.basketfield2 }} +
+ {% endif %} +
+
+ {# Positionsdetails #}
-

Positionsdetails

+

Position

-
-
+
+
Produkt {{ orderpos.product.title }}
-
+
Menge {{ orderpos.count }}
-
- Preis (netto) +
+ Preis netto {{ orderpos.priceAllNetto|number_format(2, ',', '.') }} €
- {% if orderpos.order %} -
- Auftragsnummer - {{ orderpos.order.alias }} +
+ Preis brutto + {{ orderpos.priceAllBrutto|number_format(2, ',', '.') }} € +
+ {% if articleCalc %} +
+ Konfiguration +
    + {% for opt in articleCalc.getOptions %} + {% if opt is not instanceof('\\PSC\\Library\\Calc\\Option\\Type\\Hidden') and opt.isValid() %} +
  • + {{ opt.name }}: + {{ opt.value }} +
  • + {% endif %} + {% endfor %} +
{% endif %}
{# Uploads #} - {% if orderpos.uploads|length > 0 %} + {% if position.uploadTypeObject %} + {% if position.uploadTypeObject.uploads|length > 0 %}
-

Druckdaten ({{ orderpos.uploads|length }})

+

Druckdaten ({{ position.uploadTypeObject.uploads|length }})

    - {% for upload in orderpos.uploads %} + {% for upload in position.uploadTypeObject.uploads %}
  • - {{ upload.name }} + {{ upload.filename }} {% if upload.typ %} {{ upload.typ }} {% endif %}
    - @@ -122,16 +183,24 @@
{% endif %} + {% endif %} {# Aktionen #} {% if orderpos.externalApprovalStatus is null %}

Ihre Entscheidung

-
-
- - -
-
- - -
-
+
+ +
+ {% elseif orderpos.externalApprovalMessage %} +
+

Mitteilung

+

{{ orderpos.externalApprovalMessage }}

{% endif %} diff --git a/src/new/src/PSC/Shop/QueueBundle/Type/Mail.php b/src/new/src/PSC/Shop/QueueBundle/Type/Mail.php index 6450462bf..0691c6d18 100755 --- a/src/new/src/PSC/Shop/QueueBundle/Type/Mail.php +++ b/src/new/src/PSC/Shop/QueueBundle/Type/Mail.php @@ -41,6 +41,7 @@ use PSC\System\SettingsBundle\Service\Log; use PSC\System\SettingsBundle\Service\Printing; use PSC\System\SettingsBundle\Service\TemplateVars; use Ramsey\Uuid\Uuid; +use Symfony\Bridge\Twig\Mime\TemplatedEmail; use Symfony\Bridge\Twig\Mime\WrappedTemplatedEmail; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; @@ -394,7 +395,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface 'shop' => $shop, ]; try { - $message = new Email() + $message = new TemplatedEmail() ->subject($subject->render($params)) ->from($from->render($params)) ->to(trim($to->render($params))); @@ -476,7 +477,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface 'shop' => $shop, ]; try { - $message = new Email() + $message = new TemplatedEmail() ->subject($subject->render($params)) ->from($from->render($params)) ->to(trim($to->render($params))); @@ -551,7 +552,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface 'shop' => $shop, ]; try { - $message = new Email() + $message = new TemplatedEmail() ->subject($subject->render($params)) ->from($from->render($params)) ->to(trim($to->render($params))); @@ -628,7 +629,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface 'shop' => $shop, ]; try { - $message = new Email() + $message = new TemplatedEmail() ->subject($subject->render($params)) ->from($from->render($params)) ->to(trim($to->render($params))); @@ -702,7 +703,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface $params['doc'] = $objDoc; $params['packageLink'] = '/apps/backend/order/detail/package/printpartner/' . $event->getPosition(); try { - $message = new Email() + $message = new TemplatedEmail() ->subject($subject->render($params)) ->from($from->render($params)) ->to($to->render($params)); @@ -746,7 +747,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface $position = $positionRepo->findOneBy(['uuid' => $event->getPosition()]); $templateVars->loadOrder($position->getOrder()->getUuid()); try { - $message = new Email() + $message = new TemplatedEmail() ->subject($subject->render($templateVars->getPosTwigVars($position->getUuid()))) ->from($from->render($templateVars->getPosTwigVars($position->getUuid()))) ->to($to->render($templateVars->getPosTwigVars($position->getUuid()))); @@ -765,7 +766,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface if ($html) { $message->html($html->render(array_merge($templateVars->getPosTwigVars($position->getUuid(), [ - 'email' => new WrappedTemplatedEmail($this->_template, $html), + 'email' => new WrappedTemplatedEmail($this->_template, $message), ])))); } @@ -916,7 +917,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface ) { $templateVars->loadOrder($event->getOrder()); try { - $message = new Email() + $message = new TemplatedEmail() ->subject($subject->render($templateVars->getTwigVars())) ->from($from->render($templateVars->getTwigVars())) ->to(trim($to->render($templateVars->getTwigVars()))); @@ -935,7 +936,7 @@ class Mail implements QueueInterface, ConfigurableElementInterface if ($html) { $message->html($html->render(array_merge($templateVars->getTwigVars(), [ - 'email' => new WrappedTemplatedEmail($this->_template, $html), + 'email' => new WrappedTemplatedEmail($this->_template, $message), ]))); } @@ -1265,7 +1266,6 @@ class Mail implements QueueInterface, ConfigurableElementInterface ], ); $this->_mailer->send($message); - die(); } catch (\Exception $e) { $this->_logService->createLogEntry( $templateVars->getOrder()->getShop(), diff --git a/src/new/src/PSC/System/UpdateBundle/Migrations/Version20260311100002.php b/src/new/src/PSC/System/UpdateBundle/Migrations/Version20260311100002.php new file mode 100644 index 000000000..5ec9523e2 --- /dev/null +++ b/src/new/src/PSC/System/UpdateBundle/Migrations/Version20260311100002.php @@ -0,0 +1,11 @@ +entityManager->getConnection()->executeQuery("ALTER TABLE orderspos ADD COLUMN IF NOT EXISTS external_approval_message TEXT NULL DEFAULT NULL;"); + } +} diff --git a/src/new/templates/backend_tailwind_base.html.twig b/src/new/templates/backend_tailwind_base.html.twig index 8bf277041..828540fd3 100644 --- a/src/new/templates/backend_tailwind_base.html.twig +++ b/src/new/templates/backend_tailwind_base.html.twig @@ -49,13 +49,18 @@ {% if is_granted('ROLE_ADMIN') %} {{ render(controller('\\PSC\\System\\SettingsBundle\\Controller\\FtpController::myDataTailwindAction')) }} -
+ {% endif %} -

{{ date("now")|date('d.m.Y H:i:s') }}

-

+


+

{{ date("now")|date('d.m.Y H:i:s') }}

+

+ {% if is_granted('ROLE_ADMIN') %} v{{ versionService.release }} ({{ versionService.datum }}) + {% else %} + v{{ versionService.release }} ({{ versionService.datum }}) + {% endif %}

@@ -72,8 +77,10 @@
{{ render(controller('PSC\\Backend\\DashboardBundle\\Controller\\ShopController::myEditableShopsTailwindAction', { tw: true })) }}
+ {% if is_granted('ROLE_ADMIN') %} + {% endif %}
{% if app.request.locale == 'de_DE' %} diff --git a/src/new/var/plugins/Custom/PSC/CollectLayouter/Model/Upload.php b/src/new/var/plugins/Custom/PSC/CollectLayouter/Model/Upload.php new file mode 100644 index 000000000..26b32edac --- /dev/null +++ b/src/new/var/plugins/Custom/PSC/CollectLayouter/Model/Upload.php @@ -0,0 +1,31 @@ +uploads[] = $upload; + } +} diff --git a/src/new/var/plugins/Custom/PSC/CollectLayouter/Queue/Render.php b/src/new/var/plugins/Custom/PSC/CollectLayouter/Queue/Render.php index 1f5eef594..f7373a1ab 100755 --- a/src/new/var/plugins/Custom/PSC/CollectLayouter/Queue/Render.php +++ b/src/new/var/plugins/Custom/PSC/CollectLayouter/Queue/Render.php @@ -18,7 +18,7 @@ use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormBuilderInterface; -require_once (__DIR__ .'/../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Item.php'); +require_once __DIR__ . '/../../../../../../src/PSC/Shop/EntityBundle/Lagacy/TP_Basket_Item.php'; #[AutoconfigureTag('queues')] class Render implements QueueInterface, ConfigurableElementInterface @@ -34,7 +34,6 @@ class Render implements QueueInterface, ConfigurableElementInterface */ private $_pdf; - function __construct(EntityManagerInterface $entityManager, Pdf $pdf) { $this->_entityManager = $entityManager; @@ -67,25 +66,13 @@ class Render implements QueueInterface, ConfigurableElementInterface return 'Form Based Renderer'; } - public function getForm(FormBuilderInterface $builder, $form_options, EventInterface $event) - { + public function getForm(FormBuilderInterface $builder, $form_options, EventInterface $event) {} - } + public function injectDocument(Form $form, EventInterface $event, Queue $objQueue) {} - public function injectDocument(Form $form, EventInterface $event, Queue $objQueue) - { + public function setFormData(Form $form, EventInterface $event, Queue $queueObj) {} - } - - public function setFormData(Form $form, EventInterface $event, Queue $queueObj) - { - - } - - public function getTemplate() - { - - } + public function getTemplate() {} /** * @param EventInterface $event @@ -94,31 +81,46 @@ class Render implements QueueInterface, ConfigurableElementInterface */ public function execute(EventInterface $event, Queue $doc) { - try { - set_time_limit(0); - $orderspos = $this->_entityManager->getRepository('PSC\Shop\EntityBundle\Entity\Orderpos') - ->findby(['layouterMode' => 102, 'renderPrint' => 1]); + $orderspos = $this->_entityManager + ->getRepository('PSC\Shop\EntityBundle\Entity\Orderpos') + ->findby(['layouterMode' => 102, 'renderPrint' => 1]); /** @var Orderpos $pos */ - foreach($orderspos as $pos) { + foreach ($orderspos as $pos) { /** @var \TP_Basket_Item $objPosition */ - $objPosition = unserialize(($pos->getData())); - if($objPosition->getLayouterId() != "") { - if(!file_exists('/data/www/old/market/steplayouter/basket/' . $pos->getOrder()->getUid() . '/' . $pos->getPos())) { - mkdir('/data/www/old/market/steplayouter/basket/' . $pos->getOrder()->getUid() . '/' . $pos->getPos(), 0777, true); + $objPosition = unserialize($pos->getData()); + if ($objPosition->getLayouterId() != '') { + if (!file_exists( + '/data/www/old/market/steplayouter/basket/' . $pos->getOrder()->getUid() . '/' . $pos->getPos(), + )) { + mkdir( + '/data/www/old/market/steplayouter/basket/' . $pos->getOrder()->getUid() . '/' + . $pos->getPos(), + 0777, + true, + ); } - $layoutDesignData = $this->_entityManager - ->getRepository(Layoutdesigndata::class)->findOneBy(array('uuid' => $objPosition->getLayouterId())); + ->getRepository(Layoutdesigndata::class) + ->findOneBy(array('uuid' => $objPosition->getLayouterId())); - if($layoutDesignData) { + if ($layoutDesignData) { $data = $layoutDesignData->getDesign(); - $outfile = '/data/www/old/market/steplayouter/basket/' . $pos->getOrder()->getUid() . '/' . $pos->getPos() . '/' . $pos->getOrder()->getAlias() . '_' . $pos->getPos() . '.pdf'; + $outfile = + '/data/www/old/market/steplayouter/basket/' + . $pos->getOrder()->getUid() + . '/' + . $pos->getPos() + . '/' + . $pos->getOrder()->getAlias() + . '_' + . $pos->getPos() + . '.pdf'; copy($data['pdf'], $outfile); } @@ -127,11 +129,7 @@ class Render implements QueueInterface, ConfigurableElementInterface $this->_entityManager->persist($pos); $this->_entityManager->flush(); } - } - - - } catch (\Exception $e) { echo $e->getLine(); echo $e->getMessage(); @@ -145,5 +143,5 @@ class Render implements QueueInterface, ConfigurableElementInterface { return $this->_error; } +} -} \ No newline at end of file diff --git a/src/new/var/plugins/Custom/PSC/CollectLayouter/Service/CollectLayouterUpload.php b/src/new/var/plugins/Custom/PSC/CollectLayouter/Service/CollectLayouterUpload.php new file mode 100644 index 000000000..a84cd7d8a --- /dev/null +++ b/src/new/var/plugins/Custom/PSC/CollectLayouter/Service/CollectLayouterUpload.php @@ -0,0 +1,39 @@ +getPluginSettingModule('collectlayouter', 'uploadCollectLayouter'); + } +} diff --git a/src/new/var/plugins/Custom/PSC/CollectLayouter/Transformer/CollectLayouter.php b/src/new/var/plugins/Custom/PSC/CollectLayouter/Transformer/CollectLayouter.php new file mode 100644 index 000000000..e3e0d2197 --- /dev/null +++ b/src/new/var/plugins/Custom/PSC/CollectLayouter/Transformer/CollectLayouter.php @@ -0,0 +1,42 @@ +getOrder()->getUid() . '/' . $posEntity->getPos(); + $outFile = $outDir . '/' . $posEntity->getOrder()->getAlias() . '_' . $posEntity->getPos() . '.pdf'; + + if (file_exists($outFile)) { + $up = new Upload(); + $up->setFileName($posEntity->getOrder()->getAlias() . '_' . $posEntity->getPos() . '.pdf'); + $up->setTyp('pdf'); + $up->setPath( + '/apps/market/steplayouter/basket/' + . $posEntity->getOrder()->getUid() + . '/' + . $posEntity->getPos() + . '/' + . $posEntity->getOrder()->getAlias() + . '_' + . $posEntity->getPos() + . '.pdf', + ); + $upload->addUpload($up); + } + $position->setUploadTypeObject($upload); + } + + public function toDb(Position $position, Orderpos $posEntity, PosDoc $posDoc): void {} +} diff --git a/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Model/Upload.php b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Model/Upload.php new file mode 100644 index 000000000..523103e4e --- /dev/null +++ b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Model/Upload.php @@ -0,0 +1,31 @@ +uploads[] = $upload; + } +} diff --git a/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Queue/Render.php b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Queue/Render.php index a6b82e1c3..84a27a5a5 100644 --- a/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Queue/Render.php +++ b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Queue/Render.php @@ -60,7 +60,6 @@ class Render implements QueueInterface, ConfigurableElementInterface { try { set_time_limit(0); - $orderspos = $this->entityManager ->getRepository(Orderpos::class) ->findby(['layouterMode' => 106, 'renderPrint' => 1]); diff --git a/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Service/LaufkartenUpload.php b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Service/LaufkartenUpload.php new file mode 100644 index 000000000..f07f045ec --- /dev/null +++ b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Service/LaufkartenUpload.php @@ -0,0 +1,39 @@ +getPluginSettingModule('laufkartenlayouter', 'active'); + } +} diff --git a/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Transformer/Laufkarten.php b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Transformer/Laufkarten.php new file mode 100644 index 000000000..74b1ef5c7 --- /dev/null +++ b/src/new/var/plugins/Custom/PSC/LaufkartenLayouter/Transformer/Laufkarten.php @@ -0,0 +1,42 @@ +getOrder()->getUid() . '/' . $posEntity->getPos(); + $outFile = $outDir . '/' . $posEntity->getOrder()->getAlias() . '_' . $posEntity->getPos() . '.pdf'; + + if (file_exists($outFile)) { + $up = new Upload(); + $up->setFileName($posEntity->getOrder()->getAlias() . '_' . $posEntity->getPos() . '.pdf'); + $up->setTyp('pdf'); + $up->setPath( + '/apps/market/steplayouter/basket/' + . $posEntity->getOrder()->getUid() + . '/' + . $posEntity->getPos() + . '/' + . $posEntity->getOrder()->getAlias() + . '_' + . $posEntity->getPos() + . '.pdf', + ); + $upload->addUpload($up); + } + $position->setUploadTypeObject($upload); + } + + public function toDb(Position $position, Orderpos $posEntity, PosDoc $posDoc): void {} +} diff --git a/src/new/var/plugins/Custom/PSC/R2_Pitchprint/Controller/Backend/DesignController.php b/src/new/var/plugins/Custom/PSC/R2_Pitchprint/Controller/Backend/DesignController.php index e1825a960..291ccd068 100755 --- a/src/new/var/plugins/Custom/PSC/R2_Pitchprint/Controller/Backend/DesignController.php +++ b/src/new/var/plugins/Custom/PSC/R2_Pitchprint/Controller/Backend/DesignController.php @@ -57,10 +57,17 @@ class DesignController extends AbstractController } if (isset($output['data'])) { foreach ($output['data']['__items'] as $item) { + if(strpos($item, 'folder')!== false) { $data = $this->getItems($data, $item); + } } + foreach ($output['data']['items'] as $item) + { + if (isset($item['unit'])) { + $data['designs'][] = $item; + } + } } - return [ 'designs' => $data, 'product' => $product, @@ -73,7 +80,7 @@ class DesignController extends AbstractController if (isset($itemResult['data']['unit'])) { $data['designs'][] = $itemResult['data']; } - if (!isset($itemResult['data']['unit']) && isset($itemResult['data']['items'])) { + if (!isset($itemResult['data']['unit']) && isset($itemResult['data']['__items'])) { $data['folders'][] = $itemResult['data']; } return $data; diff --git a/src/new/var/plugins/System/PSC/XmlCalc/Producer/Producer.php b/src/new/var/plugins/System/PSC/XmlCalc/Producer/Producer.php index eede28656..03cd43329 100755 --- a/src/new/var/plugins/System/PSC/XmlCalc/Producer/Producer.php +++ b/src/new/var/plugins/System/PSC/XmlCalc/Producer/Producer.php @@ -104,6 +104,10 @@ class Producer implements IUiProducer, IProducerHydrateModel, ICalcNeedContact */ $specProd = $this->product->getSpecialProductTypeObject(); + if (isset($specProd->getParams()['type'])) { + $this->engine->setActiveArticle($specProd->getParams()['type']); + } + $this->engine->setVariables($specProd->getParams()); if ($this->contact && $this->contact->getAccountType()->value > 1) { $this->engine->setVariable('contact.accountType', $this->contact->getAccountType()->value); @@ -194,6 +198,21 @@ class Producer implements IUiProducer, IProducerHydrateModel, ICalcNeedContact 'required' => [], ]; + if ($this->engine->getArticles()->count() > 1) { + $temp['properties']['type'] = [ + 'type' => 'string', + 'title' => 'Typ', + 'oneOf' => [], + 'default' => $this->engine->getArticle()->getName(), + ]; + foreach ($this->engine->getArticles() as $article) { + $temp['properties']['type']['oneOf'][] = [ + 'title' => $article->getName(), + 'const' => $article->getName(), + ]; + } + } + foreach ($this->engine->getArticle()->getOptions() as $option) { if (!$option->isValid()) { continue; diff --git a/src/new/var/tailwind/backend.built.css b/src/new/var/tailwind/backend.built.css index f618b64ea..013a4e77a 100644 --- a/src/new/var/tailwind/backend.built.css +++ b/src/new/var/tailwind/backend.built.css @@ -1037,6 +1037,10 @@ html { margin-left: 1rem; } +.ml-5{ + margin-left: 1.25rem; +} + .ml-auto{ margin-left: auto; } @@ -1190,6 +1194,10 @@ html { height: 2.5rem; } +.h-12{ + height: 3rem; +} + .h-16{ height: 4rem; } @@ -1274,6 +1282,10 @@ html { width: 2.75rem; } +.w-12{ + width: 3rem; +} + .w-16{ width: 4rem; } @@ -1521,6 +1533,10 @@ html { cursor: pointer; } +.resize-none{ + resize: none; +} + .resize{ resize: both; } @@ -1551,6 +1567,10 @@ html { grid-template-columns: repeat(12, minmax(0, 1fr)); } +.grid-cols-2{ + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + .grid-cols-4{ grid-template-columns: repeat(4, minmax(0, 1fr)); } @@ -1746,6 +1766,10 @@ html { white-space: nowrap; } +.whitespace-pre-line{ + white-space: pre-line; +} + .whitespace-pre-wrap{ white-space: pre-wrap; } @@ -1889,6 +1913,11 @@ html { border-color: rgb(209 213 219 / var(--tw-border-opacity)); } +.border-green-200{ + --tw-border-opacity: 1; + border-color: rgb(187 247 208 / var(--tw-border-opacity)); +} + .border-psc-200{ --tw-border-opacity: 1; border-color: rgb(226 128 119 / var(--tw-border-opacity)); @@ -1988,6 +2017,11 @@ html { background-color: rgb(220 252 231 / var(--tw-bg-opacity)); } +.bg-green-50{ + --tw-bg-opacity: 1; + background-color: rgb(240 253 244 / var(--tw-bg-opacity)); +} + .bg-green-600{ --tw-bg-opacity: 1; background-color: rgb(22 163 74 / var(--tw-bg-opacity)); @@ -2127,6 +2161,10 @@ html { padding: 1.25rem; } +.p-6{ + padding: 1.5rem; +} + .p-8{ padding: 2rem; } @@ -2346,6 +2384,10 @@ html { line-height: 2.25rem; } +.leading-snug{ + line-height: 1.375; +} + .tracking-tight{ letter-spacing: -0.025em; } @@ -2404,6 +2446,11 @@ html { color: rgb(22 163 74 / var(--tw-text-opacity)); } +.text-green-700{ + --tw-text-opacity: 1; + color: rgb(21 128 61 / var(--tw-text-opacity)); +} + .text-green-800{ --tw-text-opacity: 1; color: rgb(22 101 52 / var(--tw-text-opacity)); @@ -3283,6 +3330,11 @@ html { --tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity)); } +.focus\:ring-gray-400:focus{ + --tw-ring-opacity: 1; + --tw-ring-color: rgb(156 163 175 / var(--tw-ring-opacity)); +} + .focus\:ring-gray-500:focus{ --tw-ring-opacity: 1; --tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity)); diff --git a/src/new/version.yaml b/src/new/version.yaml index da4873b8b..3df17c5ff 100755 --- a/src/new/version.yaml +++ b/src/new/version.yaml @@ -1,8 +1,15 @@ info: - datum: 10.03.2026 - release: 2.3.3 + datum: 19.03.2026 + release: 2.3.4 changelog: + - version: 2.3.4 + datum: 19.03.2026 + changes: + - "Auftragssuche nach EMail" + - "Freigabeprozess für Externe implementiert (Aktion, Events)" + - "Kalkulation in Auftrag bearbeiten kann mehrere Produkte pro XML" + - "Kosmetische änderungen für eingeschränkte Benutzer" - version: 2.3.3 datum: 10.03.2026 changes: diff --git a/src/old/application/modules/default/controllers/BasketController.php b/src/old/application/modules/default/controllers/BasketController.php index d0e88b581..3d51ca533 100755 --- a/src/old/application/modules/default/controllers/BasketController.php +++ b/src/old/application/modules/default/controllers/BasketController.php @@ -4807,7 +4807,7 @@ class BasketController extends TP_Controller_Action $articleSession = new TP_Layoutersession(); $articleSess = $articleSession->getLayouterArticle($artikel->getLayouterId()); - $art->layouter_mode = 4; + $art->layouter_mode = $articleSess->getLayouterModus(); if ($articleSess->getLayouterModus() == 2) { $articleSess->copyToBasketStepLayouter($order, $art, $articleSess->getArticleId()); @@ -5244,6 +5244,9 @@ class BasketController extends TP_Controller_Action if ($article->confirmExternal) { $art->status = 90; $order->status = 90; + $order->save(); + $art->save(); + $dbMongo = TP_Mongo::getInstance(); $dbMongo->Job->insertOne(array( 'shop' => $this->shop->id, diff --git a/src/old/market/steplayouter/basket/295/1/AF-11.03.2026-89_1.pdf b/src/old/market/steplayouter/basket/295/1/AF-11.03.2026-89_1.pdf new file mode 100644 index 000000000..499dacf60 Binary files /dev/null and b/src/old/market/steplayouter/basket/295/1/AF-11.03.2026-89_1.pdf differ