From 285e0e2d337f0a5c1642f56b20897a5508674fa6 Mon Sep 17 00:00:00 2001 From: Thomas Peterson Date: Fri, 6 Mar 2026 17:10:38 +0100 Subject: [PATCH] Fixes --- .../docker-compose/docker-compose.local.yml | 14 +- .../Platform/Completions/ModelClient.php | 16 +- .../PSC/Component/ApiBundle/Api/Shop/Get.php | 44 +- .../Repository/ShopContactRepository.php | 41 +- .../views/backend/settings/index.html.twig | 6 +- .../Custom/PSC/FormBuilder/Api/Ai/Chat.php | 40 ++ .../FormBuilderTS/src/components/Gui.vue | 50 ++- .../src/components/app/AiPanel.vue | 159 +++++++ .../src/components/app/XmlView.vue | 13 +- .../app/properties/SelectElement.vue | 10 +- .../app/properties/SelectSpecial.vue | 5 - .../FormBuilderTS/src/i18n/de.json | 9 +- .../FormBuilderTS/src/i18n/en.json | 9 +- .../FormBuilder/FormBuilderTS/src/lib/api.ts | 16 + .../FormBuilderTS/src/stores/Global.ts | 41 ++ .../FormBuilder/FormBuilderTS/vite.config.ts | 2 +- .../public/formbuilderts/assets/index.css | 2 +- .../public/formbuilderts/assets/index.js | 146 +++--- .../Service/FormBuilderAiService.php | 419 ++++++++++++++++++ .../LaufkartenLayouter/Model/OcrMarker.php | 6 +- .../Custom/PSC/WMD_API/Api/ExportPrintJob.php | 124 ++++-- .../src/modules/product/ProductForm.tsx | 16 +- .../Invoice/InvoiceTS/src/services/shop.ts | 2 +- .../public/invoicets/assets/index.css | 2 +- .../public/invoicets/assets/index.js | 58 +-- 25 files changed, 1028 insertions(+), 222 deletions(-) create mode 100644 src/new/var/plugins/Custom/PSC/FormBuilder/Api/Ai/Chat.php create mode 100644 src/new/var/plugins/Custom/PSC/FormBuilder/FormBuilderTS/src/components/app/AiPanel.vue create mode 100644 src/new/var/plugins/Custom/PSC/FormBuilder/Service/FormBuilderAiService.php diff --git a/.docker/docker-compose/docker-compose.local.yml b/.docker/docker-compose/docker-compose.local.yml index 63eb8965e..581b318e7 100644 --- a/.docker/docker-compose/docker-compose.local.yml +++ b/.docker/docker-compose/docker-compose.local.yml @@ -46,13 +46,13 @@ services: networks: - network restart: always -# deploy: -# resources: -# reservations: -# devices: -# - driver: nvidia -# count: 1 # alternatively, use `count: all` for all GPUs -# capabilities: [gpu] + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: 1 # alternatively, use `count: all` for all GPUs + capabilities: [gpu] webhook: image: tarampampam/webhook-tester:2 restart: always diff --git a/src/new/src/PSC/Component/AiBundle/Platform/Completions/ModelClient.php b/src/new/src/PSC/Component/AiBundle/Platform/Completions/ModelClient.php index 74a067861..6ba8626c5 100644 --- a/src/new/src/PSC/Component/AiBundle/Platform/Completions/ModelClient.php +++ b/src/new/src/PSC/Component/AiBundle/Platform/Completions/ModelClient.php @@ -18,7 +18,7 @@ use Symfony\Contracts\HttpClient\HttpClientInterface; */ final class ModelClient implements ModelClientInterface { - private readonly EventSourceHttpClient $httpClient; + private readonly HttpClientInterface $httpClient; public function __construct( HttpClientInterface $httpClient, @@ -44,13 +44,23 @@ final class ModelClient implements ModelClientInterface */ public function request(Model $model, array|string $payload, array $options = []): RawResultInterface { - $headers = ['Content-Type' => 'application/json']; + $headers = [ + 'Content-Type' => 'application/json', + // Lowercase 'accept' ist wichtig: EventSourceHttpClient prüft exakt $options['headers']['accept'] + // mit ??= — uppercase 'Accept' würde NICHT matchen und trotzdem text/event-stream setzen. + 'accept' => 'application/json', + ]; if ($this->apiKey) { $headers['Authorization'] = 'Bearer ' . $this->apiKey; } $body = array_merge($payload, ['model' => $model->getName()]); + // Ollama-spezifische Optionen (z.B. num_ctx) direkt in den Body mergen + if (!empty($options['ollama_options'])) { + $body['options'] = $options['ollama_options']; + } + // Tools in OpenAI-Format bringen: {type: "function", function: {name, description, parameters}} if (!empty($options['tools'])) { $body['tools'] = array_map( @@ -77,7 +87,7 @@ final class ModelClient implements ModelClientInterface $response = $this->httpClient->request('POST', rtrim($this->baseUrl, '/') . $this->path, [ 'headers' => $headers, 'json' => $body, - 'timeout' => 120, + 'timeout' => 180, ]); return new RawHttpResult($response); 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 71a7494e1..d04feb993 100755 --- a/src/new/src/PSC/Component/ApiBundle/Api/Shop/Get.php +++ b/src/new/src/PSC/Component/ApiBundle/Api/Shop/Get.php @@ -4,33 +4,47 @@ namespace PSC\Component\ApiBundle\Api\Shop; use Doctrine\ORM\EntityManagerInterface; use Nelmio\ApiDocBundle\Attribute\Model; -use OpenApi\Attributes as OA; +use Nelmio\ApiDocBundle\Attribute\Security; use OpenApi\Attributes\JsonContent; use OpenApi\Attributes\Response; use OpenApi\Attributes\Tag; use PSC\Component\ApiBundle\Dto\Error\NotFound; use PSC\Component\ApiBundle\Dto\Shop\Shops; -use PSC\Component\ApiBundle\Model\Shop; -use PSC\Component\ApiBundle\Model\Shop\Domain; +use PSC\Shop\EntityBundle\Repository\ShopContactRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\Response as HttpResponse; -use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Security\Http\Attribute\IsGranted; -use Symfony\Component\Yaml\Yaml; class Get extends AbstractController { - private EntityManagerInterface $entityManager; - private \PSC\Component\ApiBundle\Hydrate\Shop $hydrateShop; - public function __construct( - EntityManagerInterface $entityManager, - \PSC\Component\ApiBundle\Hydrate\Shop $hydrateShop, - ) { - $this->entityManager = $entityManager; - $this->hydrateShop = $hydrateShop; + private EntityManagerInterface $entityManager, + private \PSC\Component\ApiBundle\Hydrate\Shop $hydrateShop, + private ShopContactRepository $shopContactRepository, + ) {} + + #[Response( + response: 200, + 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: '/my_shops', methods: ['GET'])] + #[IsGranted('ROLE_SHOP')] + public function myShops(): JsonResponse + { + $shops = $this->entityManager->getRepository(\PSC\Shop\EntityBundle\Entity\Shop::class)->findAll(); + + $data = []; + /** @var \PSC\Shop\EntityBundle\Entity\Shop $shop */ + foreach ($shops as $shop) { + $data[] = $this->hydrateShop->hydrateToModel($shop); + } + + return $this->json(new Shops\Output($data)); } #[Response( @@ -45,7 +59,7 @@ class Get extends AbstractController #[IsGranted('ROLE_SHOP')] public function allAction(): JsonResponse { - $shops = $this->entityManager->getRepository(\PSC\Shop\EntityBundle\Entity\Shop::class)->findAll(); + $shops = $this->shopContactRepository->myEditableShops($this->getUser()); $data = []; /** @var \PSC\Shop\EntityBundle\Entity\Shop $shop */ diff --git a/src/new/src/PSC/Shop/EntityBundle/Repository/ShopContactRepository.php b/src/new/src/PSC/Shop/EntityBundle/Repository/ShopContactRepository.php index 739eafc70..a7b0a86d9 100755 --- a/src/new/src/PSC/Shop/EntityBundle/Repository/ShopContactRepository.php +++ b/src/new/src/PSC/Shop/EntityBundle/Repository/ShopContactRepository.php @@ -13,9 +13,11 @@ namespace PSC\Shop\EntityBundle\Repository; +use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Common\Collections\ArrayCollection; -use Doctrine\ORM\EntityRepository; +use Doctrine\Persistence\ManagerRegistry; use PSC\Shop\EntityBundle\Entity\Contact; +use PSC\Shop\EntityBundle\Entity\ShopContact; /** * ShopContactRepository @@ -26,8 +28,13 @@ use PSC\Shop\EntityBundle\Entity\Contact; * @package PSC\Shop\Entity * @subpackage Repositorys */ -class ShopContactRepository extends EntityRepository +class ShopContactRepository extends ServiceEntityRepository { + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ShopContact::class); + } + /** * Gibt einen Shop per Apikey zurück * @@ -42,12 +49,13 @@ class ShopContactRepository extends EntityRepository public function myEditableShops(Contact $contact) { - $query = $this->getEntityManager()->createQuery( - ' + $query = $this + ->getEntityManager() + ->createQuery(' SELECT sc FROM PSC\Shop\EntityBundle\Entity\ShopContact sc JOIN sc.shop s - WHERE sc.contact = :id AND sc.admin = 1 ORDER BY sc.admin ASC, s.title ASC', - )->setParameter('id', $contact->getId()); + WHERE sc.contact = :id AND sc.admin = 1 ORDER BY sc.admin ASC, s.title ASC') + ->setParameter('id', $contact->getId()); try { $result = $query->execute(); $tmpCollection = new ArrayCollection(); @@ -62,12 +70,15 @@ class ShopContactRepository extends EntityRepository public function myEditableShopsWithNoDeleted(Contact $contact) { - $query = $this->getEntityManager()->createQuery( - ' + $query = $this + ->getEntityManager() + ->createQuery( + ' SELECT sc FROM PSC\Shop\EntityBundle\Entity\ShopContact sc JOIN sc.shop s WHERE sc.contact = :id AND s.deleted = 0 AND sc.admin = 1 ORDER BY sc.admin ASC, s.title ASC', - )->setParameter('id', $contact->getId()); + ) + ->setParameter('id', $contact->getId()); try { $result = $query->execute(); $tmpCollection = new ArrayCollection(); @@ -82,14 +93,16 @@ class ShopContactRepository extends EntityRepository public function changeSelectedShop(Contact $contact, $shop_uuid) { - $this->getEntityManager() + $this + ->getEntityManager() ->createQuery(' UPDATE PSC\Shop\EntityBundle\Entity\ShopContact sc SET sc.selected = 0 WHERE sc.contact = :id AND sc.selected = 1') ->setParameter('id', $contact->getId()) ->execute(); - $this->getEntityManager() + $this + ->getEntityManager() ->createQuery(' UPDATE PSC\Shop\EntityBundle\Entity\ShopContact sc SET sc.selected = 1 @@ -101,7 +114,8 @@ class ShopContactRepository extends EntityRepository public function updateAdmin($contactId, $shopId, $admin = true) { - $this->createQueryBuilder('sc') + $this + ->createQueryBuilder('sc') ->update() ->set('sc.admin', '?1') ->setParameter(1, $admin) @@ -114,7 +128,8 @@ class ShopContactRepository extends EntityRepository public function resetAdmin($contactId, $admin = true) { - $this->createQueryBuilder('sc') + $this + ->createQueryBuilder('sc') ->update() ->set('sc.admin', '?1') ->setParameter(1, $admin) diff --git a/src/new/src/PSC/System/SettingsBundle/Resources/views/backend/settings/index.html.twig b/src/new/src/PSC/System/SettingsBundle/Resources/views/backend/settings/index.html.twig index 557832da6..f02b2b26a 100755 --- a/src/new/src/PSC/System/SettingsBundle/Resources/views/backend/settings/index.html.twig +++ b/src/new/src/PSC/System/SettingsBundle/Resources/views/backend/settings/index.html.twig @@ -452,7 +452,7 @@ - + @@ -486,12 +486,12 @@
AnbieterEmpfohlenes ModellAPI Key nötigBase URL
Ollamallama3.2 / mistralNeinhttp://localhost:11434
Ollamaqwen2.5-coder:3b / llama3.2 / mistralNeinhttp://localhost:11434
Anthropicclaude-sonnet-4-6Ja-
OpenAIgpt-4oJa-
Googlegemini-2.0-flashJa-