From c49defb78ca94536c80ff58fce26d7a90ec5ed29 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sat, 22 Feb 2025 11:59:01 +0100
Subject: [PATCH 01/17] fix: update `getCustomerFiles` method signature in
 `AbstractOrder`

Updated the `getCustomerFiles` method signature in `AbstractOrder.php` to accept an optional
boolean parameter `$parsing`. Method can now be customized to return parsed file information or raw
data.
---
 src/QUI/ERP/Order/AbstractOrder.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/QUI/ERP/Order/AbstractOrder.php b/src/QUI/ERP/Order/AbstractOrder.php
index 9d80675b..fdb8e9b2 100644
--- a/src/QUI/ERP/Order/AbstractOrder.php
+++ b/src/QUI/ERP/Order/AbstractOrder.php
@@ -2321,7 +2321,7 @@ public function clearCustomerFiles(): void
         // TODO: Implement clearCustomerFiles() method.
     }
 
-    public function getCustomerFiles(): array
+    public function getCustomerFiles(bool $parsing = false): array
     {
         // TODO: Implement getCustomerFiles() method.
         return [];
-- 
GitLab


From 48eef9144d1f71edb3fb720430b77a1cdf186c08 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 08:27:41 +0100
Subject: [PATCH 02/17] chore(phpstan): update phpstan version in
 phive/phars.xml

Updated the version of `phpstan` from `1.11.8` to `1.*` and set the installed version as `1.12.13`
in .phive/phars.xml. This should ensure we're always using the latest version of `phpstan` that
matches the specified range.
---
 .phive/phars.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.phive/phars.xml b/.phive/phars.xml
index 5bfa092b..cccdab55 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <phive xmlns="https://phar.io/phive">
-  <phar name="phpstan" version="1.11.8" installed="1.11.8" location="./tools/phpstan" copy="false"/>
+  <phar name="phpstan" version="1.*" installed="1.12.13" location="./tools/phpstan" copy="false"/>
   <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="false"/>
   <phar name="phpcs" version="^3.10.1" installed="3.10.1" location="./tools/phpcs" copy="false"/>
   <phar name="phpcbf" version="^3.10.1" installed="3.10.1" location="./tools/phpcbf" copy="false"/>
-- 
GitLab


From b7d4519e6299fbb0be025db4aa7d38472b0a1c1a Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 08:42:02 +0100
Subject: [PATCH 03/17] refactor(phpstan): php8.4 null deprecated

---
 phpstan-baseline.neon                         | 676 ------------------
 src/QUI/ERP/Order/AbstractOrder.php           |   6 +-
 src/QUI/ERP/Order/Order.php                   |  12 +-
 src/QUI/ERP/Order/OrderInProcess.php          |  18 +-
 src/QUI/ERP/Order/OrderView.php               |   6 +-
 .../ERP/Order/Output/OutputProviderOrder.php  |  26 +-
 src/QUI/ERP/Order/Search.php                  |   6 +-
 src/QUI/ERP/Order/Utils/DataLayer.php         |   4 +-
 src/QUI/ERP/Order/Utils/Utils.php             |   2 +-
 9 files changed, 41 insertions(+), 715 deletions(-)

diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 45f1aecc..e69de29b 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -1,676 +0,0 @@
-parameters:
-	ignoreErrors:
-		-
-			message: "#^Parameter \\#6 \\$User of static method QUI\\\\ERP\\\\Accounting\\\\Payments\\\\Transactions\\\\Factory\\:\\:createPaymentTransaction\\(\\) expects null, QUI\\\\Interfaces\\\\Users\\\\User given\\.$#"
-			count: 1
-			path: ajax/backend/addPayment.php
-
-		-
-			message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 1
-			path: ajax/backend/createInvoice.php
-
-		-
-			message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 1
-			path: ajax/backend/createInvoice.php
-
-		-
-			message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
-			count: 1
-			path: ajax/backend/createSalesOrder.php
-
-		-
-			message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 1
-			path: ajax/backend/post.php
-
-		-
-			message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 1
-			path: ajax/backend/post.php
-
-		-
-			message: "#^Parameter \\#2 \\$User of class QUI\\\\ERP\\\\Order\\\\Basket\\\\BasketOrder constructor expects QUI\\\\Users\\\\User\\|null, QUI\\\\Interfaces\\\\Users\\\\User given\\.$#"
-			count: 1
-			path: ajax/frontend/basket/controls/basket.php
-
-		-
-			message: "#^Using nullsafe method call on non\\-nullable type QUI\\\\ERP\\\\Products\\\\Product\\\\ProductList\\. Use \\-\\> instead\\.$#"
-			count: 1
-			path: ajax/frontend/basket/removePos.php
-
-		-
-			message: "#^Parameter \\#2 \\$User of class QUI\\\\ERP\\\\Order\\\\Basket\\\\BasketOrder constructor expects QUI\\\\Users\\\\User\\|null, QUI\\\\Interfaces\\\\Users\\\\User given\\.$#"
-			count: 1
-			path: ajax/frontend/basket/save.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:getView\\(\\)\\.$#"
-			count: 1
-			path: ajax/frontend/order/getOrderControl.php
-
-		-
-			message: "#^Negated boolean expression is always false\\.$#"
-			count: 1
-			path: ajax/frontend/order/getStep.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Order\\\\Controls\\\\AbstractOrderingStep\\:\\:savePayment\\(\\)\\.$#"
-			count: 1
-			path: ajax/frontend/order/processing/savePayment.php
-
-		-
-			message: "#^Negated boolean expression is always false\\.$#"
-			count: 1
-			path: ajax/frontend/order/reload.php
-
-		-
-			message: "#^If condition is always true\\.$#"
-			count: 1
-			path: ajax/frontend/order/send.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:setQuantity\\(\\)\\.$#"
-			count: 1
-			path: ajax/frontend/order/setQuantity.php
-
-		-
-			message: "#^Call to method canUsedBy\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to method canUsedInErpEntity\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to method getId\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to method getId\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to method getType\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to method getType\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to method isValid\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to method setErpEntity\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Cannot call method getId\\(\\) on QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\|true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:getShipping\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:getShippingStatus\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Parameter \\#1 \\$Shipping of method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:validateShipping\\(\\) expects QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\|null, QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\|null given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Parameter \\#2 \\$User of class QUI\\\\ERP\\\\Order\\\\Basket\\\\BasketOrder constructor expects QUI\\\\Users\\\\User\\|null, QUI\\\\ERP\\\\User\\|null given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:setShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:validateShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Parameter \\$status of method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:setShippingStatus\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Property QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:\\$ShippingStatus has unknown class QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status as its type\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/AbstractOrder.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:getProductSetParentUuid\\(\\)\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Basket/Basket.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:getQuantity\\(\\)\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Basket/Basket.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:getUuid\\(\\)\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Basket/Basket.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:toArticle\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Basket/Basket.php
-
-		-
-			message: "#^Class QUI\\\\ERP\\\\Order\\\\Exception referenced with incorrect case\\: QUI\\\\Erp\\\\Order\\\\Exception\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Basket/Basket.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:getQuantity\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Basket/BasketGuest.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:getQuantity\\(\\)\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Basket/BasketOrder.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:setQuantity\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Basket/BasketOrder.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:toArray\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Basket/BasketOrder.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:toArticle\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Basket/BasketOrder.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\FieldInterface\\:\\:getAttributesForUniqueField\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Basket/Product.php
-
-		-
-			message: "#^Class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary not found\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Controls/Order/Order.php
-
-		-
-			message: "#^Instanceof between null and QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary will always evaluate to false\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Controls/Order/Order.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Order\\\\AbstractOrder\\:\\:save\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Controls/OrderProcess/Checkout.php
-
-		-
-			message: "#^Negated boolean expression is always false\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Controls/OrderProcess/Checkout.php
-
-		-
-			message: "#^Negated boolean expression is always false\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Controls/OrderProcess/CustomerData.php
-
-		-
-			message: "#^Parameter \\#2 \\$Step of method QUI\\\\ERP\\\\Order\\\\AbstractOrderProcessProvider\\:\\:getDisplay\\(\\) expects null, \\$this\\(QUI\\\\ERP\\\\Order\\\\Controls\\\\OrderProcess\\\\Processing\\) given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Controls/OrderProcess/Processing.php
-
-		-
-			message: "#^Call to method getData\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Call to method getShipping\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Call to method getShippingStatus\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Call to static method getInstance\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Handler\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Instanceof between \\*NEVER\\* and QUI\\\\ERP\\\\Products\\\\Product\\\\Types\\\\VariantChild will always evaluate to false\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Parameter \\$Invoice of method QUI\\\\ERP\\\\Order\\\\EventHandling\\:\\:onQuiqqerInvoiceTemporaryInvoicePostEnd\\(\\) has invalid type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Parameter \\$InvoiceTemporary of method QUI\\\\ERP\\\\Order\\\\EventHandling\\:\\:onQuiqqerInvoiceTemporaryInvoicePostEnd\\(\\) has invalid type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Parameter \\$SalesOrder of method QUI\\\\ERP\\\\Order\\\\EventHandling\\:\\:onQuiqqerSalesOrdersSaveEnd\\(\\) has invalid type QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Result of \\|\\| is always true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Unreachable statement \\- code above always terminates\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/EventHandling.php
-
-		-
-			message: "#^Comparison operation \"\\!\\=\" between ''\\|'0'\\|array\\{\\}\\|false and 0 results in an error\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Factory.php
-
-		-
-			message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOpenedOrders.php
-
-		-
-			message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOpenedOrders.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductTypeInterface\\:\\:getImage\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
-
-		-
-			message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
-
-		-
-			message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
-
-		-
-			message: "#^Cannot call method getTitle\\(\\) on QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\|true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Order\\\\OrderInterface\\:\\:getAttribute\\(\\)\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Mail.php
-
-		-
-			message: "#^Call to method createPDF\\(\\) on an unknown class QUI\\\\HtmlToPdf\\\\Document\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Mail.php
-
-		-
-			message: "#^Call to method setContentHTML\\(\\) on an unknown class QUI\\\\HtmlToPdf\\\\Document\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Mail.php
-
-		-
-			message: "#^Instantiated class QUI\\\\HtmlToPdf\\\\Document not found\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Mail.php
-
-		-
-			message: "#^Method QUI\\\\Interfaces\\\\Users\\\\User\\:\\:getAddress\\(\\) invoked with 0 parameters, 1 required\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Mail.php
-
-		-
-			message: "#^Call to method getId\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Call to method toJSON\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Call to static method addressRequirement\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Utils\\\\Invoice\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Call to static method addressRequirementThreshold\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Utils\\\\Invoice\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Call to static method createSalesOrder\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\Handler\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Call to static method getInstance\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Factory\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Call to static method getInstance\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Handler\\.$#"
-			count: 6
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Cannot call method getId\\(\\) on QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\|true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^If condition is always true\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Instantiated class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception not found\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\Order\\:\\:createInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\Order\\:\\:createInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\Order\\:\\:createSalesOrder\\(\\) has invalid return type QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\Order\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\Order\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\Order\\:\\:post\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\Order\\:\\:post\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\|QUI\\\\Exception is not subtype of Throwable$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Throwing object of an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Order.php
-
-		-
-			message: "#^Call to an undefined method QUI\\\\ERP\\\\Products\\\\Interfaces\\\\ProductInterface\\:\\:toArticle\\(\\)\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Call to method getId\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Call to method toArray\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Cannot call method getId\\(\\) on QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\|true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Instantiated class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception not found\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInProcess\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInProcess\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\|QUI\\\\Exception is not subtype of Throwable$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Parameter \\#2 \\$User of class QUI\\\\ERP\\\\Order\\\\Basket\\\\BasketOrder constructor expects QUI\\\\Users\\\\User\\|null, QUI\\\\ERP\\\\User\\|null given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Throwing object of an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInProcess.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInterface\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderInterface.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInterface\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderInterface.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInterface\\:\\:getShipping\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderInterface.php
-
-		-
-			message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception is not subtype of Throwable$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderInterface.php
-
-		-
-			message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\OrderInterface\\:\\:setShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderInterface.php
-
-		-
-			message: "#^Class QUI\\\\ERP\\\\Order\\\\Exception referenced with incorrect case\\: QUI\\\\Erp\\\\Order\\\\Exception\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderProcess.php
-
-		-
-			message: "#^Left side of && is always true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderProcess.php
-
-		-
-			message: "#^Parameter \\#2 \\$User of class QUI\\\\ERP\\\\Order\\\\Basket\\\\BasketOrder constructor expects QUI\\\\Users\\\\User\\|null, QUI\\\\Interfaces\\\\Users\\\\User given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderProcess.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderView.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView\\:\\:getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderView.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView\\:\\:getShipping\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderView.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView\\:\\:getShippingStatus\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderView.php
-
-		-
-			message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView\\:\\:toPDF\\(\\) has invalid return type QUI\\\\HtmlToPdf\\\\Document\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderView.php
-
-		-
-			message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\|QUI\\\\Exception is not subtype of Throwable$#"
-			count: 1
-			path: src/QUI/ERP/Order/OrderView.php
-
-		-
-			message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\OrderView\\:\\:setShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/OrderView.php
-
-		-
-			message: "#^Access to constant ECC_M on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
-
-		-
-			message: "#^Access to constant OUTPUT_IMAGE_PNG on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
-
-		-
-			message: "#^Access to constant VERSION_AUTO on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
-
-		-
-			message: "#^Call to method render\\(\\) on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
-
-		-
-			message: "#^Instantiated class chillerlan\\\\QRCode\\\\QRCode not found\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
-
-		-
-			message: "#^Instantiated class chillerlan\\\\QRCode\\\\QROptions not found\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
-
-		-
-			message: "#^Parameter \\#2 \\$key of method QUI\\\\Config\\:\\:setValue\\(\\) expects string\\|null, int given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/ProcessingStatus/Factory.php
-
-		-
-			message: "#^Parameter \\#2 \\$key of method QUI\\\\Config\\:\\:del\\(\\) expects string\\|null, int given\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/ProcessingStatus/Handler.php
-
-		-
-			message: "#^Parameter \\#2 \\$key of method QUI\\\\Config\\:\\:setValue\\(\\) expects string\\|null, int given\\.$#"
-			count: 2
-			path: src/QUI/ERP/Order/ProcessingStatus/Handler.php
-
-		-
-			message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Cannot call method getColor\\(\\) on QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\|true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Cannot call method getId\\(\\) on QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\|true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Cannot call method getTitle\\(\\) on QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\|true\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Result of closure \\(void\\) is used\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Search.php
-
-		-
-			message: "#^Call to method getPrice\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Utils/DataLayer.php
-
-		-
-			message: "#^Class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Articles\\\\Text not found\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Utils/Utils.php
-
-		-
-			message: "#^Empty array passed to foreach\\.$#"
-			count: 1
-			path: src/QUI/ERP/Order/Utils/Utils.php
diff --git a/src/QUI/ERP/Order/AbstractOrder.php b/src/QUI/ERP/Order/AbstractOrder.php
index 0a36236c..c3a3f472 100644
--- a/src/QUI/ERP/Order/AbstractOrder.php
+++ b/src/QUI/ERP/Order/AbstractOrder.php
@@ -609,7 +609,7 @@ public function recalculate($Basket = null): void
      *
      * @param QUI\Interfaces\Users\User|null $PermissionUser - optional, permission user, default = session user
      */
-    abstract public function clear(QUI\Interfaces\Users\User $PermissionUser = null);
+    abstract public function clear(null | QUI\Interfaces\Users\User $PermissionUser = null);
 
     /**
      * Refresh the order data
@@ -623,14 +623,14 @@ abstract public function refresh();
      * @param QUI\Interfaces\Users\User|null $PermissionUser - optional, permission user, default = session user
      * @throws QUI\Exception
      */
-    abstract public function update(QUI\Interfaces\Users\User $PermissionUser = null);
+    abstract public function update(null | QUI\Interfaces\Users\User $PermissionUser = null);
 
     /**
      * Delete the order
      *
      * @param QUI\Interfaces\Users\User|null $PermissionUser - optional, permission user, default = session user
      */
-    abstract public function delete(QUI\Interfaces\Users\User $PermissionUser = null);
+    abstract public function delete(null | QUI\Interfaces\Users\User $PermissionUser = null);
 
     /**
      * Is the order posted / submitted
diff --git a/src/QUI/ERP/Order/Order.php b/src/QUI/ERP/Order/Order.php
index f3ec75f6..f0fb2e48 100644
--- a/src/QUI/ERP/Order/Order.php
+++ b/src/QUI/ERP/Order/Order.php
@@ -90,7 +90,7 @@ public function refresh(): void
      * @throws QUI\Exception
      * @throws QUI\ERP\Accounting\Invoice\Exception
      */
-    public function getInvoice(): QUI\ERP\Accounting\Invoice\Invoice|QUI\ERP\Accounting\Invoice\InvoiceTemporary
+    public function getInvoice(): QUI\ERP\Accounting\Invoice\Invoice | QUI\ERP\Accounting\Invoice\InvoiceTemporary
     {
         if (!Settings::getInstance()->isInvoiceInstalled()) {
             throw new QUI\Exception([
@@ -140,8 +140,8 @@ public function getView(): OrderView
      * @throws QUI\Exception
      */
     public function createInvoice(
-        QUI\Interfaces\Users\User $PermissionUser = null
-    ): QUI\ERP\Accounting\Invoice\Invoice|QUI\ERP\Accounting\Invoice\InvoiceTemporary {
+        null | QUI\Interfaces\Users\User $PermissionUser = null
+    ): QUI\ERP\Accounting\Invoice\Invoice | QUI\ERP\Accounting\Invoice\InvoiceTemporary {
         if (Settings::getInstance()->forceCreateInvoice() === false && $this->isPosted()) {
             return $this->getInvoice();
         }
@@ -504,7 +504,7 @@ public function hasInvoice(): bool
      * @throws QUI\Exception
      * @deprecated use createInvoice
      */
-    public function post(): Invoice|InvoiceTemporary
+    public function post(): Invoice | InvoiceTemporary
     {
         return $this->createInvoice(QUI::getUsers()->getSystemUser());
     }
@@ -996,8 +996,8 @@ public function delete($PermissionUser = null): void
      * @throws Exception
      */
     public function copy(
-        QUI\Interfaces\Users\User $PermissionUser = null,
-        bool|string $globalProcessId = false
+        null | QUI\Interfaces\Users\User $PermissionUser = null,
+        bool | string $globalProcessId = false
     ): Order {
         $NewOrder = Factory::getInstance()->create();
 
diff --git a/src/QUI/ERP/Order/OrderInProcess.php b/src/QUI/ERP/Order/OrderInProcess.php
index 614bb0d4..f654ccdd 100644
--- a/src/QUI/ERP/Order/OrderInProcess.php
+++ b/src/QUI/ERP/Order/OrderInProcess.php
@@ -27,7 +27,7 @@
  */
 class OrderInProcess extends AbstractOrder implements OrderInterface, ErpEntityInterface, ErpTransactionsInterface
 {
-    protected null|string|int $orderId = null;
+    protected null | string | int $orderId = null;
 
     /**
      * Order constructor.
@@ -97,7 +97,7 @@ public function refresh(): void
         $this->setDataBaseData($data);
     }
 
-    public function getOrderId(): null|int|string
+    public function getOrderId(): null | int | string
     {
         return $this->orderId;
     }
@@ -130,7 +130,7 @@ public function getPrefixedId(): string
      * @throws Exception
      * @throws QUI\Permissions\Exception
      */
-    public function save(QUI\Interfaces\Users\User $PermissionUser = null): void
+    public function save(null | QUI\Interfaces\Users\User $PermissionUser = null): void
     {
         $this->update($PermissionUser);
     }
@@ -141,7 +141,7 @@ public function save(QUI\Interfaces\Users\User $PermissionUser = null): void
      * @throws QUI\Permissions\Exception
      * @throws Exception
      */
-    public function update(QUI\Interfaces\Users\User $PermissionUser = null): void
+    public function update(null | QUI\Interfaces\Users\User $PermissionUser = null): void
     {
         if ($this->hasPermissions($PermissionUser) === false) {
             throw new QUI\Permissions\Exception(
@@ -349,7 +349,7 @@ public function calculatePayments(): void
      * @throws QUI\Permissions\Exception
      * @throws QUI\Database\Exception
      */
-    public function delete(QUI\Interfaces\Users\User $PermissionUser = null): void
+    public function delete(null | QUI\Interfaces\Users\User $PermissionUser = null): void
     {
         if ($this->hasPermissions($PermissionUser) === false) {
             throw new QUI\Permissions\Exception(
@@ -394,7 +394,7 @@ public function isPosted(): bool
      * @throws Exception
      * @throws Exception
      */
-    public function createOrder(QUI\Interfaces\Users\User $PermissionUser = null): Order
+    public function createOrder(null | QUI\Interfaces\Users\User $PermissionUser = null): Order
     {
         QUI\ERP\Debug::getInstance()->log('OrderInProcess:: Create Order');
 
@@ -571,7 +571,7 @@ public function createOrder(QUI\Interfaces\Users\User $PermissionUser = null): O
      * @param null|QUI\Interfaces\Users\User $PermissionUser
      * @return bool
      */
-    protected function hasPermissions(QUI\Interfaces\Users\User $PermissionUser = null): bool
+    protected function hasPermissions(null | QUI\Interfaces\Users\User $PermissionUser = null): bool
     {
         if ($PermissionUser === null) {
             $PermissionUser = QUI::getUserBySession();
@@ -691,7 +691,7 @@ protected function getDataForSaving(): array
      * @throws Exception
      * @throws QUI\ExceptionStack
      */
-    public function clear($PermissionUser = null): void
+    public function clear(null | QUI\Interfaces\Users\User $PermissionUser = null): void
     {
         if ($PermissionUser === null) {
             $PermissionUser = QUI::getUserBySession();
@@ -761,7 +761,7 @@ public function hasInvoice(): bool
      * @throws Exception
      * @throws QUI\ERP\Accounting\Invoice\Exception
      */
-    public function getInvoice(): QUI\ERP\Accounting\Invoice\Invoice|QUI\ERP\Accounting\Invoice\InvoiceTemporary
+    public function getInvoice(): QUI\ERP\Accounting\Invoice\Invoice | QUI\ERP\Accounting\Invoice\InvoiceTemporary
     {
         if ($this->orderId) {
             $Order = Handler::getInstance()->get($this->getOrderId());
diff --git a/src/QUI/ERP/Order/OrderView.php b/src/QUI/ERP/Order/OrderView.php
index 74ad8925..c0cf446b 100644
--- a/src/QUI/ERP/Order/OrderView.php
+++ b/src/QUI/ERP/Order/OrderView.php
@@ -177,7 +177,7 @@ public function getCreateDate(): string
     /**
      * @return bool|QUI\ERP\Shipping\ShippingStatus\Status
      */
-    public function getShippingStatus(): bool|QUI\ERP\Shipping\ShippingStatus\Status
+    public function getShippingStatus(): bool | QUI\ERP\Shipping\ShippingStatus\Status
     {
         return $this->Order->getShippingStatus();
     }
@@ -210,7 +210,7 @@ public function getData(): array
      * @param null|QUI\Locale $Locale
      * @return string|bool
      */
-    public function getDate(QUI\Locale $Locale = null): string|bool
+    public function getDate(null | QUI\Locale $Locale = null): string | bool
     {
         if ($Locale === null) {
             $Locale = QUI::getLocale();
@@ -306,7 +306,7 @@ public function getInvoiceAddress(): Address
      * @throws QUI\Exception
      * @throws QUI\ERP\Accounting\Invoice\Exception
      */
-    public function getInvoice(): QUI\ERP\Accounting\Invoice\Invoice|QUI\ERP\Accounting\Invoice\InvoiceTemporary
+    public function getInvoice(): QUI\ERP\Accounting\Invoice\Invoice | QUI\ERP\Accounting\Invoice\InvoiceTemporary
     {
         return $this->Order->getInvoice();
     }
diff --git a/src/QUI/ERP/Order/Output/OutputProviderOrder.php b/src/QUI/ERP/Order/Output/OutputProviderOrder.php
index 3dcad38b..5e887cff 100644
--- a/src/QUI/ERP/Order/Output/OutputProviderOrder.php
+++ b/src/QUI/ERP/Order/Output/OutputProviderOrder.php
@@ -57,7 +57,7 @@ public static function getEntityType(): string
      * @param Locale|null $Locale $Locale (optional) - If ommitted use \QUI::getLocale()
      * @return string
      */
-    public static function getEntityTypeTitle(Locale $Locale = null): string
+    public static function getEntityTypeTitle(null | Locale $Locale = null): string
     {
         if (empty($Locale)) {
             $Locale = QUI::getLocale();
@@ -74,7 +74,7 @@ public static function getEntityTypeTitle(Locale $Locale = null): string
      *
      * @throws QUI\Exception
      */
-    public static function getEntity(int|string $entityId): OrderInProcess|Order
+    public static function getEntity(int | string $entityId): OrderInProcess | Order
     {
         try {
             $Order = QUI\ERP\Order\Handler::getInstance()->get($entityId);
@@ -93,7 +93,7 @@ public static function getEntity(int|string $entityId): OrderInProcess|Order
      *
      * @throws QUI\Exception
      */
-    public static function getDownloadFileName(int|string $entityId): string
+    public static function getDownloadFileName(int | string $entityId): string
     {
         return self::getEntity($entityId)->getPrefixedNumber();
     }
@@ -106,7 +106,7 @@ public static function getDownloadFileName(int|string $entityId): string
      *
      * @throws QUI\Exception
      */
-    public static function getLocale(int|string $entityId): Locale
+    public static function getLocale(int | string $entityId): Locale
     {
         $Order = self::getEntity($entityId);
         $Customer = $Order->getCustomer();
@@ -121,7 +121,7 @@ public static function getLocale(int|string $entityId): Locale
      * @return array
      * @throws QUI\Exception
      */
-    public static function getTemplateData(int|string $entityId): array
+    public static function getTemplateData(int | string $entityId): array
     {
         $Order = self::getEntity($entityId);
         $OrderView = $Order->getView();
@@ -202,7 +202,7 @@ public static function getTemplateData(int|string $entityId): array
      * @param User $User
      * @return bool
      */
-    public static function hasDownloadPermission(int|string $entityId, User $User): bool
+    public static function hasDownloadPermission(int | string $entityId, User $User): bool
     {
         if (!QUI::getUsers()->isAuth($User) || QUI::getUsers()->isNobodyUser($User)) {
             return false;
@@ -227,7 +227,7 @@ public static function hasDownloadPermission(int|string $entityId, User $User):
      *
      * @throws QUI\Exception
      */
-    public static function getEmailAddress(int|string $entityId): bool|string
+    public static function getEmailAddress(int | string $entityId): bool | string
     {
         $Customer = self::getEntity($entityId)->getCustomer();
 
@@ -246,7 +246,7 @@ public static function getEmailAddress(int|string $entityId): bool|string
      *
      * @throws QUI\Exception
      */
-    public static function getMailSubject(int|string $entityId): string
+    public static function getMailSubject(int | string $entityId): string
     {
         $Order = self::getEntity($entityId);
         $Customer = $Order->getCustomer();
@@ -266,7 +266,7 @@ public static function getMailSubject(int|string $entityId): string
      *
      * @throws QUI\Exception
      */
-    public static function getMailBody(int|string $entityId): string
+    public static function getMailBody(int | string $entityId): string
     {
         $Order = self::getEntity($entityId);
         $Customer = $Order->getCustomer();
@@ -418,7 +418,7 @@ public static function getCustomerVariables(QUI\ERP\User $Customer): array
      * @param $date
      * @return false|string
      */
-    public static function dateFormat($date): bool|string
+    public static function dateFormat($date): bool | string
     {
         // date
         $localeCode = QUI::getLocale()->getLocalesByLang(
@@ -446,7 +446,7 @@ public static function dateFormat($date): bool|string
      * @param Order $Order
      * @return string|false - Raw <img> "src" attribute with base64 image data or false if code can or must not be generated.
      */
-    protected static function getEpcQrCodeImageImgSrc(Order $Order): bool|string
+    protected static function getEpcQrCodeImageImgSrc(Order $Order): bool | string
     {
         try {
             // Check currency (must be EUR)
@@ -474,7 +474,9 @@ protected static function getEpcQrCodeImageImgSrc(Order $Order): bool|string
 
 
         // Prefer bank account set in SEPA module if available
-        if (class_exists('QUI\ERP\Payments\SEPA\Provider') && QUI::getPackageManager()->isInstalled('quiqqer/payment-sepa')) {
+        if (class_exists('QUI\ERP\Payments\SEPA\Provider') && QUI::getPackageManager()->isInstalled(
+                'quiqqer/payment-sepa'
+            )) {
             $creditorBankAccount = QUI\ERP\Payments\SEPA\Provider::getCreditorBankAccount();
         } else {
             $creditorBankAccount = BankAccounts::getCompanyBankAccount();
diff --git a/src/QUI/ERP/Order/Search.php b/src/QUI/ERP/Order/Search.php
index c9761658..49e8269f 100644
--- a/src/QUI/ERP/Order/Search.php
+++ b/src/QUI/ERP/Order/Search.php
@@ -44,7 +44,7 @@ class Search extends Singleton
     /**
      * @var array|bool
      */
-    protected array|bool $limit = [0, 20];
+    protected array | bool $limit = [0, 20];
 
     /**
      * @var string
@@ -78,7 +78,7 @@ class Search extends Singleton
      * @param string $filter
      * @param array|string|null $value
      */
-    public function setFilter(string $filter, array|string|null $value): void
+    public function setFilter(string $filter, array | string | null $value): void
     {
         if ($value === null) {
             return;
@@ -157,7 +157,7 @@ public function clearFilter(): void
      * @param int|string $from
      * @param int|string $to
      */
-    public function limit(int|string $from, int|string $to): void
+    public function limit(int | string $from, int | string $to): void
     {
         $this->limit = [(int)$from, (int)$to];
     }
diff --git a/src/QUI/ERP/Order/Utils/DataLayer.php b/src/QUI/ERP/Order/Utils/DataLayer.php
index eee4e1c1..6759f73e 100644
--- a/src/QUI/ERP/Order/Utils/DataLayer.php
+++ b/src/QUI/ERP/Order/Utils/DataLayer.php
@@ -77,7 +77,7 @@ public static function parseProduct(Product $Product, $Locale = null): array
         return $product;
     }
 
-    public static function parseArticle(QUI\ERP\Accounting\Article $Article, QUI\Locale $Locale = null): array
+    public static function parseArticle(QUI\ERP\Accounting\Article $Article, null | QUI\Locale $Locale = null): array
     {
         try {
             $Product = Products::getProduct($Article->getId());
@@ -104,7 +104,7 @@ public static function parseArticle(QUI\ERP\Accounting\Article $Article, QUI\Loc
         return $item;
     }
 
-    public static function parseOrder(QUI\ERP\Order\OrderInterface $Order, QUI\Locale $Locale = null): array
+    public static function parseOrder(QUI\ERP\Order\OrderInterface $Order, null | QUI\Locale $Locale = null): array
     {
         $calculations = $Order->getArticles()->getCalculations();
         $tax = 0;
diff --git a/src/QUI/ERP/Order/Utils/Utils.php b/src/QUI/ERP/Order/Utils/Utils.php
index fefe6376..c972f67e 100644
--- a/src/QUI/ERP/Order/Utils/Utils.php
+++ b/src/QUI/ERP/Order/Utils/Utils.php
@@ -278,7 +278,7 @@ public static function isPaymentChangeable(
     public static function importProductsToBasketList(
         QUI\ERP\Products\Product\ProductList $List,
         array $products = [],
-        QUI\ERP\Order\AbstractOrder|QUI\ERP\Order\Basket\Basket $Order = null
+        null | QUI\ERP\Order\AbstractOrder | QUI\ERP\Order\Basket\Basket $Order = null
     ): QUI\ERP\Products\Product\ProductList {
         if (!is_array($products)) {
             $products = [];
-- 
GitLab


From a5f3b8e5056fb2d3a43086397e92661728de4588 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 08:50:36 +0100
Subject: [PATCH 04/17] fix(phpstan): update abstractorder and other files for
 consistent function behaviour

Updated AbstractOrder.php to return null instead of false in getShippingStatus() when the shipping
status is not set. This makes the method's behaviour more consistent.

Updated Search.php to add a condition check for class existence before retrieving shipping status.
This ensures that the code will not fail if the class is not defined.

Modified DataLayer.php to add a condition check for class existence before retrieving shipping.

Added @phpstan-ignore-next-line in Utils.php to silence phpstan for the next line of code.

Related: quiqqer/order#172
---
 src/QUI/ERP/Order/AbstractOrder.php   |  8 ++++----
 src/QUI/ERP/Order/Search.php          | 14 ++++++++------
 src/QUI/ERP/Order/Utils/DataLayer.php |  2 +-
 src/QUI/ERP/Order/Utils/Utils.php     |  1 +
 4 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/src/QUI/ERP/Order/AbstractOrder.php b/src/QUI/ERP/Order/AbstractOrder.php
index c3a3f472..01915c29 100644
--- a/src/QUI/ERP/Order/AbstractOrder.php
+++ b/src/QUI/ERP/Order/AbstractOrder.php
@@ -2228,15 +2228,15 @@ public function setProcessingStatus(ProcessingStatus\Status|int $status): void
      * Return the shipping status
      * -> This method only works if shipping is installed
      *
-     * @return bool|QUI\ERP\Shipping\ShippingStatus\Status|null
+     * @return QUI\ERP\Shipping\ShippingStatus\Status|null
      */
-    public function getShippingStatus(): bool|QUI\ERP\Shipping\ShippingStatus\Status|null
+    public function getShippingStatus(): QUI\ERP\Shipping\ShippingStatus\Status|null
     {
         if (
             !QUI::getPackageManager()->isInstalled('quiqqer/shipping')
             || !class_exists('QUI\ERP\Shipping\ShippingStatus\Handler')
         ) {
-            return false;
+            return null;
         }
 
         if ($this->ShippingStatus !== null) {
@@ -2251,7 +2251,7 @@ public function getShippingStatus(): bool|QUI\ERP\Shipping\ShippingStatus\Status
 
         // use default status
         if ($this->ShippingStatus === null) {
-            return false;
+            return null;
         }
 
         return $this->ShippingStatus;
diff --git a/src/QUI/ERP/Order/Search.php b/src/QUI/ERP/Order/Search.php
index 49e8269f..bc493279 100644
--- a/src/QUI/ERP/Order/Search.php
+++ b/src/QUI/ERP/Order/Search.php
@@ -527,7 +527,7 @@ protected function parseListForGrid(array $data): array
             } catch (QUI\Exception $Exception) {
                 QUI\System\Log::writeException($Exception);
 
-                $result[] = $fillFields($entry);
+                $fillFields($entry);
                 continue;
             }
 
@@ -604,12 +604,14 @@ protected function parseListForGrid(array $data): array
                 $orderData['shipping_status_title'] = Handler::EMPTY_VALUE;
                 $orderData['shipping_status_color'] = '';
 
-                $ShippingStatus = $Order->getShippingStatus();
+                if (class_exists('QUI\ERP\Shipping\ShippingStatus\Status')) {
+                    $ShippingStatus = $Order->getShippingStatus();
 
-                if ($ShippingStatus) {
-                    $orderData['shipping_status_id'] = $ShippingStatus->getId();
-                    $orderData['shipping_status_title'] = $ShippingStatus->getTitle();
-                    $orderData['shipping_status_color'] = $ShippingStatus->getColor();
+                    if ($ShippingStatus) {
+                        $orderData['shipping_status_id'] = $ShippingStatus->getId();
+                        $orderData['shipping_status_title'] = $ShippingStatus->getTitle();
+                        $orderData['shipping_status_color'] = $ShippingStatus->getColor();
+                    }
                 }
             }
 
diff --git a/src/QUI/ERP/Order/Utils/DataLayer.php b/src/QUI/ERP/Order/Utils/DataLayer.php
index 6759f73e..e6c54efb 100644
--- a/src/QUI/ERP/Order/Utils/DataLayer.php
+++ b/src/QUI/ERP/Order/Utils/DataLayer.php
@@ -119,7 +119,7 @@ public static function parseOrder(QUI\ERP\Order\OrderInterface $Order, null | QU
             'tax' => $tax
         ];
 
-        if ($Order->getShipping()) {
+        if (class_exists('QUI\ERP\Shipping\Types\ShippingEntry') && $Order->getShipping()) {
             $order['shipping'] = $Order->getShipping()->getPrice();
         }
 
diff --git a/src/QUI/ERP/Order/Utils/Utils.php b/src/QUI/ERP/Order/Utils/Utils.php
index c972f67e..ee5cfce6 100644
--- a/src/QUI/ERP/Order/Utils/Utils.php
+++ b/src/QUI/ERP/Order/Utils/Utils.php
@@ -429,6 +429,7 @@ public static function getMergedProductList($products): array
     {
         $newProductList = [];
         $getProductIndex = function ($product) use (&$newProductList) {
+            // @phpstan-ignore-next-line
             foreach ($newProductList as $index => $p) {
                 $p1 = serialize(self::getCompareProductArray($product));
                 $p2 = serialize(self::getCompareProductArray($p));
-- 
GitLab


From f11a7d4bb8ca9064b865cc2d26d4a1d09b38b7bf Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 08:52:20 +0100
Subject: [PATCH 05/17] refactor(phpunit): ensure consistent handling of
 processing status id

This commit improves the way processing status id is handled across different methods in the
ProcessingStatus module. Now, we consistently cast processing status id as string before passing it
to the config setter methods, eliminating any potential issues that might occur due to variable
type inconsistencies. Changes are applied to the Factory and Handler classes alike.

Related: quiqqer/order#172
---
 src/QUI/ERP/Order/ProcessingStatus/Factory.php | 4 ++--
 src/QUI/ERP/Order/ProcessingStatus/Handler.php | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/QUI/ERP/Order/ProcessingStatus/Factory.php b/src/QUI/ERP/Order/ProcessingStatus/Factory.php
index b9aa7d28..42ebf8ee 100644
--- a/src/QUI/ERP/Order/ProcessingStatus/Factory.php
+++ b/src/QUI/ERP/Order/ProcessingStatus/Factory.php
@@ -31,7 +31,7 @@ class Factory extends QUI\Utils\Singleton
      * @throws QUI\Exception
      * @todo permissions
      */
-    public function createProcessingStatus(int|string $id, string $color, array $title): void
+    public function createProcessingStatus(int | string $id, string $color, array $title): void
     {
         $list = Handler::getInstance()->getList();
         $id = (int)$id;
@@ -48,7 +48,7 @@ public function createProcessingStatus(int|string $id, string $color, array $tit
         $Package = QUI::getPackage('quiqqer/order');
         $Config = $Package->getConfig();
 
-        $Config->setValue('processing_status', $id, $color);
+        $Config->setValue('processing_status', (string)$id, $color);
         $Config->save();
 
         // translations
diff --git a/src/QUI/ERP/Order/ProcessingStatus/Handler.php b/src/QUI/ERP/Order/ProcessingStatus/Handler.php
index 37b209f1..403d6a00 100644
--- a/src/QUI/ERP/Order/ProcessingStatus/Handler.php
+++ b/src/QUI/ERP/Order/ProcessingStatus/Handler.php
@@ -149,7 +149,7 @@ public function deleteProcessingStatus(int | string $id): void
         QUI\Translator::publish('quiqqer/order');
 
         // update config
-        $this->OrderConfig->del('processing_status', $Status->getId());
+        $this->OrderConfig->del('processing_status', (string)$Status->getId());
         $this->OrderConfig->save();
     }
 
@@ -168,7 +168,7 @@ public function setProcessingStatusNotification(int $id, bool $notify): void
         $Status = $this->getProcessingStatus($id);
 
         // update config
-        $this->OrderConfig->setValue('processing_status_notification', $Status->getId(), $notify ? "1" : "0");
+        $this->OrderConfig->setValue('processing_status_notification', (string)$Status->getId(), $notify ? "1" : "0");
         $this->OrderConfig->save();
     }
 
@@ -213,7 +213,7 @@ public function updateProcessingStatus(int | string $id, int | string $color, ar
         QUI\Translator::publish('quiqqer/order');
 
         // update config
-        $this->OrderConfig->setValue('processing_status', $Status->getId(), $color);
+        $this->OrderConfig->setValue('processing_status', (string)$Status->getId(), $color);
         $this->OrderConfig->save();
     }
 
-- 
GitLab


From e8a56bf244b851fef34ef04db61a039aabd6ad37 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 09:06:42 +0100
Subject: [PATCH 06/17] fix(phpstan): better error handling and class usage

This commit fixes several areas:

1. It changes class type in BasketOrder from QUI\\Users\\User to QUI\\Interfaces\\Users\\User.

2. It refactors Order to better handle if statements and moves verification of class existence up
to the beginning. Fix involves assuming that function getInvoiceAddress and getDeliveryAddress
always return a non-null value. It also updates on how we check class exists for Shipping data.

3. In OrderInProcess, now we check if method 'toArticle' exists on the Product object before
calling it and applies similar class checking like in Order for Shipping data.

4. Corrects and standardizes the casing for exception catching in OrderProcess.

In summary, these changes lead to a safer and cleaner code base by addressing potential Null
Pointer Exceptions and ensuring the existence of classes before they are being called.

Related: quiqqer/order#172
---
 src/QUI/ERP/Order/Basket/BasketOrder.php |  2 +-
 src/QUI/ERP/Order/Order.php              | 26 ++++++++++--------------
 src/QUI/ERP/Order/OrderInProcess.php     | 19 +++++++++--------
 src/QUI/ERP/Order/OrderProcess.php       |  5 +++--
 4 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/src/QUI/ERP/Order/Basket/BasketOrder.php b/src/QUI/ERP/Order/Basket/BasketOrder.php
index 469f1f63..790d4aa0 100644
--- a/src/QUI/ERP/Order/Basket/BasketOrder.php
+++ b/src/QUI/ERP/Order/Basket/BasketOrder.php
@@ -61,7 +61,7 @@ class BasketOrder
      * Basket constructor.
      *
      * @param string $orderHash - ID of the order
-     * @param ?QUI\Users\User $User
+     * @param ?QUI\Interfaces\Users\User $User
      *
      * @throws Exception
      * @throws QUI\Exception
diff --git a/src/QUI/ERP/Order/Order.php b/src/QUI/ERP/Order/Order.php
index f0fb2e48..18f736a4 100644
--- a/src/QUI/ERP/Order/Order.php
+++ b/src/QUI/ERP/Order/Order.php
@@ -216,10 +216,6 @@ public function createInvoice(
 
         // set the data to the temporary invoice
         $payment = '';
-
-        $invoiceAddress = '';
-        $invoiceAddressId = '';
-
         $deliveryAddress = '';
         $deliveryAddressId = '';
 
@@ -227,16 +223,14 @@ public function createInvoice(
             $payment = $this->getPayment()->getId();
         }
 
-        if ($this->getInvoiceAddress()) {
-            $invoiceAddress = $this->getInvoiceAddress()->toJSON();
-            $invoiceAddressId = $this->getInvoiceAddress()->getUUID();
-        }
+        $invoiceAddress = $this->getInvoiceAddress()->toJSON();
+        $invoiceAddressId = $this->getInvoiceAddress()->getUUID();
 
         if (empty($invoiceAddressId)) {
             $invoiceAddressId = $this->getCustomer()->getStandardAddress()->getUUID();
         }
 
-        if ($this->getDeliveryAddress()) {
+        if ($this->getDeliveryAddress()->getUUID()) {
             $deliveryAddress = $this->getDeliveryAddress()->toJSON();
             $deliveryAddressId = $this->getDeliveryAddress()->getUUID();
 
@@ -579,16 +573,18 @@ class_exists('QUI\ERP\Accounting\Invoice\Invoice')
         $shippingData = '';
         $shippingStatus = null;
 
-        $Shipping = $this->getShipping();
+        if (class_exists('QUI\ERP\Shipping\Types\ShippingEntry')) {
+            $Shipping = $this->getShipping();
 
-        if ($Shipping) {
-            $shippingId = $Shipping->getId();
-            $shippingData = $Shipping->toJSON();
+            if ($Shipping) {
+                $shippingId = $Shipping->getId();
+                $shippingData = $Shipping->toJSON();
+            }
         }
 
-        if (QUI::getPackageManager()->isInstalled('quiqqer/shipping')) {
+        if (class_exists('QUI\ERP\Shipping\ShippingStatus\Status')) {
             $ShippingStatus = $this->getShippingStatus();
-            $shippingStatus = $ShippingStatus ? $ShippingStatus->getId() : null;
+            $shippingStatus = $ShippingStatus?->getId();
         }
 
         // project name
diff --git a/src/QUI/ERP/Order/OrderInProcess.php b/src/QUI/ERP/Order/OrderInProcess.php
index f654ccdd..3a20cc52 100644
--- a/src/QUI/ERP/Order/OrderInProcess.php
+++ b/src/QUI/ERP/Order/OrderInProcess.php
@@ -246,8 +246,9 @@ public function addPriceFactors(array $priceFactors = []): void
 
         foreach ($products as $Product) {
             try {
-                /* @var QUI\ERP\Order\Basket\Product $Product */
-                $ArticleList->addArticle($Product->toArticle(null, false));
+                if (method_exists($Product, 'toArticle')) {
+                    $ArticleList->addArticle($Product->toArticle(null, false));
+                }
             } catch (Exception $Exception) {
                 QUI\System\Log::writeDebugException($Exception);
             }
@@ -640,16 +641,18 @@ protected function getDataForSaving(): array
         $shippingData = '';
         $shippingStatus = null;
 
-        $Shipping = $this->getShipping();
+        if (class_exists('QUI\ERP\Shipping\Types\ShippingEntry')) {
+            $Shipping = $this->getShipping();
 
-        if ($Shipping) {
-            $shippingId = $Shipping->getId();
-            $shippingData = $Shipping->toArray();
+            if ($Shipping) {
+                $shippingId = $Shipping->getId();
+                $shippingData = $Shipping->toArray();
+            }
         }
 
-        if (QUI::getPackageManager()->isInstalled('quiqqer/shipping')) {
+        if (class_exists('QUI\ERP\Shipping\ShippingStatus\Status')) {
             $ShippingStatus = $this->getShippingStatus();
-            $shippingStatus = $ShippingStatus ? $ShippingStatus->getId() : null;
+            $shippingStatus = $ShippingStatus?->getId();
         }
 
         return [
diff --git a/src/QUI/ERP/Order/OrderProcess.php b/src/QUI/ERP/Order/OrderProcess.php
index a4eaf65b..d3e413cb 100644
--- a/src/QUI/ERP/Order/OrderProcess.php
+++ b/src/QUI/ERP/Order/OrderProcess.php
@@ -824,6 +824,7 @@ protected function checkProcessing(): bool | string
         $paymentIsSuccessful = false;
         $Payment = $Order->getPayment();
 
+        // @phpstan-ignore-next-line
         if ($Payment && $Payment->isSuccessful($Order->getUUID())) {
             $paymentIsSuccessful = true;
         }
@@ -1316,7 +1317,7 @@ public function getOrder(): ?AbstractOrder
                     return $this->Order;
                 }
             }
-        } catch (QUI\Erp\Order\Exception) {
+        } catch (QUI\ERP\Order\Exception) {
         }
 
 
@@ -1327,7 +1328,7 @@ public function getOrder(): ?AbstractOrder
             if (!$OrderInProcess->getOrderId()) {
                 $this->Order = $OrderInProcess;
             }
-        } catch (QUI\Erp\Order\Exception) {
+        } catch (QUI\ERP\Order\Exception) {
         }
 
         if ($this->Order === null) {
-- 
GitLab


From 222a914c976f70770d513339b8482f902b8019e0 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 09:07:53 +0100
Subject: [PATCH 07/17] style: update code formatting and type declarations

Changes include:
- Modified code formatting to improve readability and conform to best coding practices.
- Updated type declarations using pipe (|) operator to indicate variable can hold multiple types.
- Adjusted the spacing around the pipe operator in type declarations for improved readability.
---
 src/QUI/ERP/Order/AbstractOrder.php | 22 +++++++-------
 src/QUI/ERP/Order/ErpProvider.php   | 46 ++++++++++++++---------------
 src/QUI/ERP/Order/Mail.php          |  2 +-
 3 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/src/QUI/ERP/Order/AbstractOrder.php b/src/QUI/ERP/Order/AbstractOrder.php
index 01915c29..642fa31d 100644
--- a/src/QUI/ERP/Order/AbstractOrder.php
+++ b/src/QUI/ERP/Order/AbstractOrder.php
@@ -85,7 +85,7 @@ abstract class AbstractOrder extends QUI\QDOM implements OrderInterface, ErpEnti
     /**
      * @var Status|StatusUnknown|null
      */
-    protected Status|StatusUnknown|null $Status = null;
+    protected Status | StatusUnknown | null $Status = null;
 
     /**
      * @var null|QUI\ERP\Shipping\ShippingStatus\Status
@@ -102,12 +102,12 @@ abstract class AbstractOrder extends QUI\QDOM implements OrderInterface, ErpEnti
      *
      * @var int|bool|string
      */
-    protected string|int|bool|null $invoiceId = false;
+    protected string | int | bool | null $invoiceId = false;
 
     /**
      * @var string|int|null
      */
-    protected null|int|string $customerId;
+    protected null | int | string $customerId;
 
     /**
      * @var array|null
@@ -153,7 +153,7 @@ abstract class AbstractOrder extends QUI\QDOM implements OrderInterface, ErpEnti
      *
      * @var integer|string
      */
-    protected int|string $cUser;
+    protected int | string $cUser;
 
     /**
      * @var ArticleList|null
@@ -1074,7 +1074,7 @@ public function hasDeliveryAddress(): bool
      *
      * @param array|QUI\ERP\Address $address
      */
-    public function setDeliveryAddress(array|QUI\ERP\Address $address): void
+    public function setDeliveryAddress(array | QUI\ERP\Address $address): void
     {
         if ($address instanceof QUI\ERP\Address) {
             $this->addressDelivery = $address->getAttributes();
@@ -1097,7 +1097,7 @@ public function removeDeliveryAddress(): void
      *
      * @param array|QUI\ERP\Address|QUI\Users\Address $address
      */
-    public function setInvoiceAddress(array|QUI\ERP\Address|QUI\Users\Address $address): void
+    public function setInvoiceAddress(array | QUI\ERP\Address | QUI\Users\Address $address): void
     {
         if ($address instanceof QUI\Users\Address) {
             $this->addressInvoice = $address->getAttributes();
@@ -1170,7 +1170,7 @@ public function setCurrency(QUI\ERP\Currency\Currency $Currency): void
      * @throws QUI\Exception
      * @throws ExceptionStack
      */
-    public function setCustomer(QUI\Interfaces\Users\User|array|User $User): void
+    public function setCustomer(QUI\Interfaces\Users\User | array | User $User): void
     {
         $oldCustomerId = $this->customerId;
 
@@ -1429,7 +1429,7 @@ public function isPaid(): bool
      *
      * @todo Payment->canBeUsed() noch implementieren
      */
-    public function setPayment(int|string $paymentId): void
+    public function setPayment(int | string $paymentId): void
     {
         $Payments = Payments::getInstance();
 
@@ -2193,7 +2193,7 @@ public function getProcessingStatus(): ?ProcessingStatus\Status
      *
      * @param int|ProcessingStatus\Status $status
      */
-    public function setProcessingStatus(ProcessingStatus\Status|int $status): void
+    public function setProcessingStatus(ProcessingStatus\Status | int $status): void
     {
         if ($status instanceof ProcessingStatus\Status) {
             $Status = $status;
@@ -2230,7 +2230,7 @@ public function setProcessingStatus(ProcessingStatus\Status|int $status): void
      *
      * @return QUI\ERP\Shipping\ShippingStatus\Status|null
      */
-    public function getShippingStatus(): QUI\ERP\Shipping\ShippingStatus\Status|null
+    public function getShippingStatus(): QUI\ERP\Shipping\ShippingStatus\Status | null
     {
         if (
             !QUI::getPackageManager()->isInstalled('quiqqer/shipping')
@@ -2265,7 +2265,7 @@ public function getShippingStatus(): QUI\ERP\Shipping\ShippingStatus\Status|null
      * @param int|QUI\ERP\Shipping\ShippingStatus\Status $status
      * @throws QUI\Exception
      */
-    public function setShippingStatus(int|QUI\ERP\Shipping\ShippingStatus\Status $status): void
+    public function setShippingStatus(int | QUI\ERP\Shipping\ShippingStatus\Status $status): void
     {
         if (!QUI::getPackageManager()->isInstalled('quiqqer/shipping')) {
             return;
diff --git a/src/QUI/ERP/Order/ErpProvider.php b/src/QUI/ERP/Order/ErpProvider.php
index 61c32172..1c1e7808 100644
--- a/src/QUI/ERP/Order/ErpProvider.php
+++ b/src/QUI/ERP/Order/ErpProvider.php
@@ -27,10 +27,10 @@ public static function addMenuItems(Map $Map): void
 
         if ($Accounting === null) {
             $Accounting = new Item([
-                'icon'     => 'fa fa-book',
-                'name'     => 'accounting',
-                'text'     => ['quiqqer/order', 'erp.panel.accounting.text'],
-                'opened'   => true,
+                'icon' => 'fa fa-book',
+                'name' => 'accounting',
+                'text' => ['quiqqer/order', 'erp.panel.accounting.text'],
+                'opened' => true,
                 'priority' => 1
             ]);
 
@@ -38,27 +38,27 @@ public static function addMenuItems(Map $Map): void
         }
 
         $Order = new Item([
-            'icon'     => 'fa fa-shopping-basket',
-            'name'     => 'order',
-            'text'     => ['quiqqer/order', 'erp.panel.order.text'],
-            'opened'   => true,
+            'icon' => 'fa fa-shopping-basket',
+            'name' => 'order',
+            'text' => ['quiqqer/order', 'erp.panel.order.text'],
+            'opened' => true,
             'priority' => 1
         ]);
 
         $Order->appendChild(
             new Item([
-                'icon'    => 'fa fa-plus',
-                'name'    => 'invoice-create',
-                'text'    => ['quiqqer/order', 'erp.panel.order.create.text'],
+                'icon' => 'fa fa-plus',
+                'name' => 'invoice-create',
+                'text' => ['quiqqer/order', 'erp.panel.order.create.text'],
                 'require' => 'package/quiqqer/order/bin/backend/utils/ErpMenuOrderCreate'
             ])
         );
 
         $Order->appendChild(
             new Item([
-                'icon'    => 'fa fa-shopping-basket',
-                'name'    => 'invoice-drafts',
-                'text'    => ['quiqqer/order', 'erp.panel.order.list.text'],
+                'icon' => 'fa fa-shopping-basket',
+                'name' => 'invoice-drafts',
+                'text' => ['quiqqer/order', 'erp.panel.order.list.text'],
                 'require' => 'package/quiqqer/order/bin/backend/controls/panels/Orders'
             ])
         );
@@ -83,28 +83,28 @@ public static function getMailLocale(): array
     {
         return [
             [
-                'title'       => QUI::getLocale()->get('quiqqer/order', 'mail.text.orderConfirmation.title'),
+                'title' => QUI::getLocale()->get('quiqqer/order', 'mail.text.orderConfirmation.title'),
                 'description' => QUI::getLocale()->get('quiqqer/order', 'mail.text.orderConfirmation.description'),
-                'subject'     => ['quiqqer/order', 'order.confirmation.subject'],
-                'content'     => ['quiqqer/order', 'order.confirmation.body'],
+                'subject' => ['quiqqer/order', 'order.confirmation.subject'],
+                'content' => ['quiqqer/order', 'order.confirmation.body'],
 
                 'subject.description' => ['quiqqer/order', 'order.confirmation.subject.description'],
                 'content.description' => ['quiqqer/order', 'order.confirmation.body.description']
             ],
             [
-                'title'       => QUI::getLocale()->get('quiqqer/order', 'mail.text.orderPaymentSuccess.title'),
+                'title' => QUI::getLocale()->get('quiqqer/order', 'mail.text.orderPaymentSuccess.title'),
                 'description' => QUI::getLocale()->get('quiqqer/order', 'mail.text.orderPaymentSuccess.description'),
-                'subject'     => ['quiqqer/order', 'mail.payment_success.body'],
-                'content'     => ['quiqqer/order', 'mail.payment_success.body'],
+                'subject' => ['quiqqer/order', 'mail.payment_success.body'],
+                'content' => ['quiqqer/order', 'mail.payment_success.body'],
 
                 'subject.description' => ['quiqqer/order', 'mail.description.orderPaymentSuccess.subject'],
                 'content.description' => ['quiqqer/order', 'mail.description.orderPaymentSuccess.body']
             ],
             [
-                'title'       => QUI::getLocale()->get('quiqqer/order', 'shipping.confirmation.title'),
+                'title' => QUI::getLocale()->get('quiqqer/order', 'shipping.confirmation.title'),
                 'description' => QUI::getLocale()->get('quiqqer/order', 'shipping.confirmation.description'),
-                'subject'     => ['quiqqer/order', 'shipping.order.mail.subject'],
-                'content'     => ['quiqqer/order', 'shipping.order.mail.body'],
+                'subject' => ['quiqqer/order', 'shipping.order.mail.subject'],
+                'content' => ['quiqqer/order', 'shipping.order.mail.body'],
 
                 'subject.description' => ['quiqqer/order', 'mail.description.shipping.confirmation.subject'],
                 'content.description' => ['quiqqer/order', 'mail.description.shipping.confirmation.body']
diff --git a/src/QUI/ERP/Order/Mail.php b/src/QUI/ERP/Order/Mail.php
index f58ea232..e44fd685 100644
--- a/src/QUI/ERP/Order/Mail.php
+++ b/src/QUI/ERP/Order/Mail.php
@@ -581,7 +581,7 @@ protected static function getOrderLocaleVar(OrderInterface $Order, QUI\Interface
      * @param $date
      * @return false|string
      */
-    public static function dateFormat($date): bool|string
+    public static function dateFormat($date): bool | string
     {
         // date
         $localeCode = QUI::getLocale()->getLocalesByLang(
-- 
GitLab


From 56156df7747810fceeeb3ff2305e1ee8d9c0d17c Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:07:20 +0100
Subject: [PATCH 08/17] fix(phpstan): update variable types and fix bug
 conditions

This commit brings a number of changes across multiple files. The changes include adjustment of
variable types, fixing conditions, and the optimization of method calls.

1. In src/QUI/ERP/Order/AbstractOrderProcessProvider.php, the function getDisplay has had its
parameters realigned with AbstractOrderingStep, providing a clear type definition.

2. src/QUI/ERP/Order/EventHandling.php has changed the onDetailEquipmentButtons function to expect
a ProductTypeInterface, enabling a wider range of object types to be passed in.

3. src/QUI/ERP/Order/Factory.php now only checks for an empty orderId, rather than also improperly
comparing to zero.

4. src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php, a fallback has been added for when the
method getImage does not exist on a Product object.

5. src/QUI/ERP/Order/Mail.php has been updated to use the correct customer address method based on
the user's type.

6. Lastly, in src/QUI/ERP/Order/OrderView.php, the getShippingStatus method now correctly specifies
null as a possible return type.

Related: quiqqer/order#172
---
 src/QUI/ERP/Order/AbstractOrderProcessProvider.php    |  5 +++--
 src/QUI/ERP/Order/EventHandling.php                   |  5 +++--
 src/QUI/ERP/Order/Factory.php                         |  2 +-
 .../ERP/Order/FrontendUsers/Controls/UserOrders.php   |  6 ++++--
 src/QUI/ERP/Order/Mail.php                            | 11 +++++++----
 src/QUI/ERP/Order/OrderView.php                       |  4 ++--
 6 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/QUI/ERP/Order/AbstractOrderProcessProvider.php b/src/QUI/ERP/Order/AbstractOrderProcessProvider.php
index 4aa905d8..d39f1424 100644
--- a/src/QUI/ERP/Order/AbstractOrderProcessProvider.php
+++ b/src/QUI/ERP/Order/AbstractOrderProcessProvider.php
@@ -6,6 +6,7 @@
 
 namespace QUI\ERP\Order;
 
+use QUI\ERP\Order\Controls\AbstractOrderingStep;
 use QUI\ERP\Order\Utils\OrderProcessSteps;
 
 /**
@@ -45,10 +46,10 @@ public function initSteps(OrderProcessSteps $OrderProcessSteps, OrderProcess $Or
      * The processing order provider can display a separate step in the order processing
      *
      * @param AbstractOrder $Order
-     * @param null $Step
+     * @param AbstractOrderingStep|null $Step
      * @return string
      */
-    public function getDisplay(AbstractOrder $Order, $Step = null): string
+    public function getDisplay(AbstractOrder $Order, null | AbstractOrderingStep $Step = null): string
     {
         return '';
     }
diff --git a/src/QUI/ERP/Order/EventHandling.php b/src/QUI/ERP/Order/EventHandling.php
index df36c47a..cab4b85e 100644
--- a/src/QUI/ERP/Order/EventHandling.php
+++ b/src/QUI/ERP/Order/EventHandling.php
@@ -11,6 +11,7 @@
 use QUI;
 use QUI\ERP\Accounting\Payments\Transactions\Transaction;
 use QUI\ERP\Order\Controls\OrderProcess\CustomerData;
+use QUI\ERP\Products\Interfaces\ProductTypeInterface;
 use QUI\Smarty\Collector;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Response;
@@ -392,7 +393,7 @@ public static function onPackageSetup(QUI\Package\Package $Package): void
      */
     public static function onDetailEquipmentButtons(
         Collector $Collection,
-        QUI\ERP\Products\Product\Types\AbstractType $Product
+        ProductTypeInterface $Product
     ): void {
         // add to basket -> only for complete products
         // variant products cant be added directly
@@ -400,7 +401,6 @@ public static function onDetailEquipmentButtons(
             $Product instanceof QUI\ERP\Products\Product\Product
             || $Product instanceof QUI\ERP\Products\Product\Types\VariantChild
         ) {
-            /* @var $Product QUI\ERP\Products\Product\Product */
             $AddToBasket = new QUI\ERP\Order\Controls\Buttons\ProductToBasket([
                 'Product' => $Product,
                 'input' => false
@@ -563,6 +563,7 @@ public static function onQuiqqerSalesOrdersSaveEnd(QUI\ERP\SalesOrders\SalesOrde
 
             // set shipping
             if ($SalesOrder->getShipping()) {
+                // @phpstan-ignore-next-line
                 $Order->setShipping($SalesOrder->getShipping());
             }
 
diff --git a/src/QUI/ERP/Order/Factory.php b/src/QUI/ERP/Order/Factory.php
index fa0e45e4..b73c67b1 100644
--- a/src/QUI/ERP/Order/Factory.php
+++ b/src/QUI/ERP/Order/Factory.php
@@ -83,7 +83,7 @@ public function create(
         $Config = QUI::getPackage('quiqqer/order')->getConfig();
         $orderId = $Config->getValue('order', 'orderCurrentIdIndex');
 
-        if (empty($orderId) && $orderId != 0) {
+        if (empty($orderId)) {
             $orderId = 0;
         } else {
             $orderId = (int)$orderId + 1;
diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
index 83a4ba6d..2135ea16 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
@@ -179,7 +179,7 @@ public function renderOrder(OrderInterface $Order): string
         $shippingStatus = false;
 
         if (
-            QUI::getPackageManager()->isInstalled('quiqqer/shipping')
+            class_exists('QUI\ERP\Shipping\ShippingStatus\Status')
             && $Order->getShippingStatus()
         ) {
             $shippingStatus = $Order->getShippingStatus()->getTitle();
@@ -230,7 +230,9 @@ public function renderArticle(QUI\ERP\Accounting\Article $Article): string
 
         if (!empty($Product)) {
             try {
-                $Image = $Product->getImage();
+                if (method_exists($Product, 'getImage')) {
+                    $Image = $Product->getImage();
+                }
             } catch (QUI\Exception) {
             }
         }
diff --git a/src/QUI/ERP/Order/Mail.php b/src/QUI/ERP/Order/Mail.php
index e44fd685..4613a745 100644
--- a/src/QUI/ERP/Order/Mail.php
+++ b/src/QUI/ERP/Order/Mail.php
@@ -530,14 +530,17 @@ protected static function addBCCMailAddress(QUI\Mail\Mailer $Mailer): void
     //region mail helper
 
     /**
-     * @param OrderInterface $Order
+     * @param QUI\ERP\ErpEntityInterface $Order
      * @param QUI\Interfaces\Users\User $Customer
      * @return array
-     * @throws Exception
      */
-    protected static function getOrderLocaleVar(OrderInterface $Order, QUI\Interfaces\Users\User $Customer): array
+    protected static function getOrderLocaleVar(QUI\ERP\ErpEntityInterface $Order, QUI\Interfaces\Users\User $Customer): array
     {
-        $Address = $Customer->getAddress();
+        if ($Customer instanceof QUI\ERP\User) {
+            $Address = $Customer->getAddress();
+        } else {
+            $Address = $Customer->getStandardAddress();
+        }
 
         // customer name
         $user = $Customer->getName();
diff --git a/src/QUI/ERP/Order/OrderView.php b/src/QUI/ERP/Order/OrderView.php
index c0cf446b..79fc5987 100644
--- a/src/QUI/ERP/Order/OrderView.php
+++ b/src/QUI/ERP/Order/OrderView.php
@@ -175,9 +175,9 @@ public function getCreateDate(): string
     }
 
     /**
-     * @return bool|QUI\ERP\Shipping\ShippingStatus\Status
+     * @return null|QUI\ERP\Shipping\ShippingStatus\Status
      */
-    public function getShippingStatus(): bool | QUI\ERP\Shipping\ShippingStatus\Status
+    public function getShippingStatus(): null | QUI\ERP\Shipping\ShippingStatus\Status
     {
         return $this->Order->getShippingStatus();
     }
-- 
GitLab


From fdc7309a6a3af79cb0a3a60d312494da038eec56 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:13:20 +0100
Subject: [PATCH 09/17] refactor(phpstan): improve order handling and cleanup
 code

Changes include:
- Updated `AbstractOrderingStep.php` to handle null case in `getOrder` method and modified return
type.
- Refactored `Order.php` to remove unnecessary checks and improve readability.
- Ensured safety against calling non-existent `save()` method in `Checkout.php`.
- Simplified address getting logic in `CustomerData.php`.
- Removed unnecessary check in isUserB2B function.

Related: quiqqer/order#172
---
 src/QUI/ERP/Order/Controls/AbstractOrderingStep.php | 11 ++++++++---
 src/QUI/ERP/Order/Controls/Order/Order.php          | 12 ++++--------
 .../ERP/Order/Controls/OrderProcess/Checkout.php    |  4 +++-
 .../Order/Controls/OrderProcess/CustomerData.php    | 13 +------------
 4 files changed, 16 insertions(+), 24 deletions(-)

diff --git a/src/QUI/ERP/Order/Controls/AbstractOrderingStep.php b/src/QUI/ERP/Order/Controls/AbstractOrderingStep.php
index 4a928c26..7c96473f 100644
--- a/src/QUI/ERP/Order/Controls/AbstractOrderingStep.php
+++ b/src/QUI/ERP/Order/Controls/AbstractOrderingStep.php
@@ -7,6 +7,7 @@
 namespace QUI\ERP\Order\Controls;
 
 use QUI;
+use QUI\ERP\Order\AbstractOrder;
 use QUI\Locale;
 use ReflectionClass;
 
@@ -48,11 +49,15 @@ public function getIcon(): string
     /**
      * Return the current order
      *
-     * @return QUI\ERP\Order\AbstractOrder
+     * @return AbstractOrder|null
      */
-    public function getOrder(): QUI\ERP\Order\AbstractOrder
+    public function getOrder(): ?QUI\ERP\Order\AbstractOrder
     {
-        return $this->getAttribute('Order');
+        if ($this->getAttribute('Order') instanceof QUI\ERP\Order\AbstractOrder) {
+            return $this->getAttribute('Order');
+        }
+
+        return null;
     }
 
     /**
diff --git a/src/QUI/ERP/Order/Controls/Order/Order.php b/src/QUI/ERP/Order/Controls/Order/Order.php
index 512d3554..8a4a4717 100644
--- a/src/QUI/ERP/Order/Controls/Order/Order.php
+++ b/src/QUI/ERP/Order/Controls/Order/Order.php
@@ -21,7 +21,7 @@ class Order extends QUI\Control
     /**
      * @var null|QUI\ERP\Order\AbstractOrder
      */
-    protected QUI\ERP\Order\AbstractOrder|null $Order = null;
+    protected QUI\ERP\Order\AbstractOrder | null $Order = null;
 
     /**
      * Order constructor.
@@ -83,16 +83,12 @@ public function getBody(): string
             if ($Order->hasInvoice()) {
                 $Invoice = $Order->getInvoice();
             }
-
-            if ($Invoice instanceof QUI\ERP\Accounting\Invoice\InvoiceTemporary) {
-                $View->setAttribute('downloadLink', false);
-            }
         } catch (QUI\Exception $Exception) {
             QUI\System\Log::writeDebugException($Exception);
+        }
 
-            if ($Invoice instanceof QUI\ERP\Accounting\Invoice\InvoiceTemporary) {
-                $View->setAttribute('downloadLink', false);
-            }
+        if ($Invoice instanceof QUI\ERP\Accounting\Invoice\InvoiceTemporary) {
+            $View->setAttribute('downloadLink', false);
         }
 
         switch ($this->getAttribute('template')) {
diff --git a/src/QUI/ERP/Order/Controls/OrderProcess/Checkout.php b/src/QUI/ERP/Order/Controls/OrderProcess/Checkout.php
index 52f058fd..0a269e9e 100644
--- a/src/QUI/ERP/Order/Controls/OrderProcess/Checkout.php
+++ b/src/QUI/ERP/Order/Controls/OrderProcess/Checkout.php
@@ -254,7 +254,9 @@ public function forceSave(): void
         $Order->setData('orderedWithCosts', 1);
         $Order->setData('orderedWithCostsPayment', $Payment->getId());
 
-        $Order->save();
+        if (method_exists($Order, 'save')) {
+            $Order->save();
+        }
     }
 
     /**
diff --git a/src/QUI/ERP/Order/Controls/OrderProcess/CustomerData.php b/src/QUI/ERP/Order/Controls/OrderProcess/CustomerData.php
index e62706a8..7b4c1713 100644
--- a/src/QUI/ERP/Order/Controls/OrderProcess/CustomerData.php
+++ b/src/QUI/ERP/Order/Controls/OrderProcess/CustomerData.php
@@ -64,14 +64,7 @@ public function getBody(): string
         }
 
         if (!$Address) {
-            try {
-                /* @var $User User */
-                $Address = $User->getStandardAddress();
-            } catch (QUI\Exception) {
-                // user has no address
-                // create a new standard address
-                $Address = $User->addAddress();
-            }
+            $Address = $User->getStandardAddress();
         }
 
         try {
@@ -83,10 +76,6 @@ public function getBody(): string
 
 
         $isUserB2B = function () use ($User) {
-            if (!$User) {
-                return '';
-            }
-
             if ($User->getAttribute('quiqqer.erp.isNettoUser') === QUI\ERP\Utils\User::IS_NETTO_USER) {
                 return ' selected="selected"';
             }
-- 
GitLab


From 088220b60952b2c9a926b43d32e823b3d404a87d Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:24:18 +0100
Subject: [PATCH 10/17] fix(phpunit): improve method existence checks in
 product handling code

Extended the method existence checks throughout src/QUI/ERP/Order/Basket/ files. Improved the
robustness of the code by ensuring that methods such as 'getUuid', 'getProductSetParentUuid',
'getQuantity', 'toArticle', and 'getAttributesForUniqueField' exist before calling them, thus
preventing potential undefined method errors. Removed unnecessary comments used for type hinting in
favor of functional checks.

Related: quiqqer/order#172
---
 src/QUI/ERP/Order/Basket/Basket.php      | 29 ++++++++++++++++++------
 src/QUI/ERP/Order/Basket/BasketGuest.php | 10 ++++----
 src/QUI/ERP/Order/Basket/BasketOrder.php | 18 +++++++++++----
 src/QUI/ERP/Order/Basket/Product.php     |  5 ++--
 4 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/src/QUI/ERP/Order/Basket/Basket.php b/src/QUI/ERP/Order/Basket/Basket.php
index 28dc0193..94a4eda1 100644
--- a/src/QUI/ERP/Order/Basket/Basket.php
+++ b/src/QUI/ERP/Order/Basket/Basket.php
@@ -237,10 +237,17 @@ public function save(): void
         $products = $this->List->getProducts();
 
         foreach ($products as $Product) {
-            /* @var $Product Product */
+            if (
+                !method_exists($Product, 'getUuid')
+                || !method_exists($Product, 'getProductSetParentUuid')
+                || !method_exists($Product, 'getQuantity')
+                || !method_exists($Product, 'toArticle')
+            ) {
+                continue;
+            }
+
             $fields = $Product->getFields();
 
-            /* @var $Field UniqueField */
             foreach ($fields as $Field) {
                 $Field->setChangeableStatus(false);
             }
@@ -255,7 +262,6 @@ public function save(): void
                 'fields' => []
             ];
 
-            /* @var $Field UniqueField */
             foreach ($fields as $Field) {
                 if ($Field->isCustomField()) {
                     $productData['fields'][] = $Field->getAttributes();
@@ -293,11 +299,17 @@ public function toArray(): array
         $products = $Products->getProducts();
         $result = [];
 
-        /* @var $Product Product */
         foreach ($products as $Product) {
+            if (
+                !method_exists($Product, 'getUuid')
+                || !method_exists($Product, 'getProductSetParentUuid')
+                || !method_exists($Product, 'getQuantity')
+            ) {
+                continue;
+            }
+
             $fields = [];
 
-            /* @var $Field UniqueField */
             foreach ($Product->getFields() as $Field) {
                 if (!$Field->isPublic() && !$Field->isCustomField()) {
                     continue;
@@ -456,8 +468,11 @@ public function toOrder(QUI\ERP\Order\AbstractOrder $Order): void
         $Order->clear();
 
         foreach ($products as $Product) {
+            if (!method_exists($Product, 'toArticle')) {
+                continue;
+            }
+
             try {
-                /* @var QUI\ERP\Order\Basket\Product $Product */
                 $Order->addArticle($Product->toArticle(null, false));
             } catch (QUI\Users\Exception $Exception) {
                 QUI\System\Log::writeDebugException($Exception);
@@ -503,7 +518,7 @@ protected function createNewOrder(): QUI\ERP\Order\OrderInProcess
         try {
             // select the last order in processing
             return $Orders->getLastOrderInProcessFromUser($User);
-        } catch (QUI\Erp\Order\Exception) {
+        } catch (QUI\ERP\Order\Exception) {
         }
 
         return QUI\ERP\Order\Factory::getInstance()->createOrderInProcess();
diff --git a/src/QUI/ERP/Order/Basket/BasketGuest.php b/src/QUI/ERP/Order/Basket/BasketGuest.php
index 57d6ed3a..a96a05dd 100644
--- a/src/QUI/ERP/Order/Basket/BasketGuest.php
+++ b/src/QUI/ERP/Order/Basket/BasketGuest.php
@@ -84,13 +84,13 @@ public function addProduct(Product $Product): void
 
     //endregion
 
-     /**
+    /**
      * Import the products to the basket
      *
      * @param array|null $products
      * @throws ExceptionStack
      */
-    public function import(array|null $products = []): void
+    public function import(array | null $products = []): void
     {
         $this->clear();
 
@@ -164,11 +164,13 @@ public function toArray(): array
         $products = $Products->getProducts();
         $result = [];
 
-        /* @var $Product Product */
         foreach ($products as $Product) {
+            if (!method_exists($Product, 'getQuantity')) {
+                continue;
+            }
+
             $fields = [];
 
-            /* @var $Field UniqueField */
             foreach ($Product->getFields() as $Field) {
                 if (!$Field->isPublic()) {
                     continue;
diff --git a/src/QUI/ERP/Order/Basket/BasketOrder.php b/src/QUI/ERP/Order/Basket/BasketOrder.php
index 790d4aa0..af632800 100644
--- a/src/QUI/ERP/Order/Basket/BasketOrder.php
+++ b/src/QUI/ERP/Order/Basket/BasketOrder.php
@@ -212,6 +212,16 @@ public function addProduct(Product $Product): void
         $foundProduct = false;
 
         foreach ($Products as $P) {
+            if (
+                !method_exists($Product, 'toArray')
+                || !method_exists($Product, 'getQuantity')
+                || !method_exists($P, 'toArray')
+                || !method_exists($P, 'getQuantity')
+                || !method_exists($P, 'setQuantity')
+            ) {
+                continue;
+            }
+
             $p1 = OrderProductUtils::getCompareProductArray($Product->toArray());
             $p2 = OrderProductUtils::getCompareProductArray($P->toArray());
 
@@ -352,7 +362,6 @@ public function toArray(): array
         $products = $Products->getProducts();
         $result = [];
 
-        /* @var $Product Product */
         foreach ($products as $Product) {
             $fields = [];
 
@@ -371,7 +380,7 @@ public function toArray(): array
 
             $attributes = [
                 'id' => $Product->getId(),
-                'quantity' => $Product->getQuantity(),
+                'quantity' => method_exists($Product, 'getQuantity') ? $Product->getQuantity() : 1,
                 'fields' => $fields
             ];
 
@@ -457,8 +466,9 @@ public function updateOrder(): void
 
         foreach ($products as $Product) {
             try {
-                /* @var QUI\ERP\Order\Basket\Product $Product */
-                $this->Order->addArticle($Product->toArticle(null, false));
+                if (method_exists($Product, 'toArticle')) {
+                    $this->Order->addArticle($Product->toArticle(null, false));
+                }
             } catch (QUI\Users\Exception $Exception) {
                 QUI\System\Log::writeDebugException($Exception);
             }
diff --git a/src/QUI/ERP/Order/Basket/Product.php b/src/QUI/ERP/Order/Basket/Product.php
index 5ce00569..96e7e704 100644
--- a/src/QUI/ERP/Order/Basket/Product.php
+++ b/src/QUI/ERP/Order/Basket/Product.php
@@ -90,9 +90,8 @@ public function __construct(int $pid, array $attributes = [])
         // set missing fields
         $productFields = $Product->getFields();
 
-        /* @var $Field QUI\ERP\Products\Field\Field */
         foreach ($productFields as $Field) {
-            if (!isset($fieldList[$Field->getId()])) {
+            if (!isset($fieldList[$Field->getId()]) && method_exists($Field, 'getAttributesForUniqueField')) {
                 $fieldList[$Field->getId()] = $Field->getAttributesForUniqueField();
             }
         }
@@ -108,7 +107,7 @@ public function __construct(int $pid, array $attributes = [])
      * @param $fieldValue
      * @return null|QUI\ERP\Products\Field\Field|UniqueField
      */
-    protected function importFieldData($fieldId, $fieldValue): QUI\ERP\Products\Field\Field|UniqueField|null
+    protected function importFieldData($fieldId, $fieldValue): QUI\ERP\Products\Field\Field | UniqueField | null
     {
         try {
             if (is_array($fieldValue) && isset($fieldValue['identifier'])) {
-- 
GitLab


From afb39d80913f54934d9b9509112b5fc5abf4e0ef Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:29:13 +0100
Subject: [PATCH 11/17] fix(phpstan): handle non-existing classes in
 abstractOrder.php

This commit fixes the errors arising from non-existing classes in the AbstractOrder.php

Changes include:
- Added a comment on the shipping validation
- Corrected type declaration in the reversal function signature to include the possibility of the
parameter being null.
- Checked for the existence of ShippingStatus and ShippingEntry classes before attempting to get
Shipping status and Shipping Ids, respectively. This prevents errors if these classes do not exist.

Related: quiqqer/order#172
---
 src/QUI/ERP/Order/AbstractOrder.php | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/QUI/ERP/Order/AbstractOrder.php b/src/QUI/ERP/Order/AbstractOrder.php
index 642fa31d..e5e45d5d 100644
--- a/src/QUI/ERP/Order/AbstractOrder.php
+++ b/src/QUI/ERP/Order/AbstractOrder.php
@@ -439,6 +439,7 @@ protected function setDataBaseData(array $data): void
 
             // validate shipping
             try {
+                // @phpstan-ignore-next-line
                 $this->validateShipping($this->getShipping());
             } catch (QUI\Exception) {
                 $this->shippingId = null;
@@ -473,7 +474,7 @@ protected function setDataBaseData(array $data): void
      * @param QUI\Interfaces\Users\User|null $PermissionUser
      * @return ErpEntityInterface|null
      */
-    public function reversal(string $reason = '', QUI\Interfaces\Users\User $PermissionUser = null): ?ErpEntityInterface
+    public function reversal(string $reason = '', null | QUI\Interfaces\Users\User $PermissionUser = null): ?ErpEntityInterface
     {
         $this->delete($PermissionUser);
         return null;
@@ -673,13 +674,13 @@ public function toArray(): array
             QUI\System\Log::writeDebugException($Exception);
         }
 
-        if ($this->getShippingStatus()) {
+        if (class_exists('QUI\ERP\Shipping\ShippingStatus\Status') && $this->getShippingStatus()) {
             $shippingStatus = $this->getShippingStatus()->getId();
         }
 
         $shipping = '';
 
-        if ($this->getShipping()) {
+        if (class_exists('QUI\ERP\Shipping\Types\ShippingEntry') && $this->getShipping()) {
             $shipping = $this->getShipping()->getId();
         }
 
-- 
GitLab


From 19046b7bfc806ab7ead59536f5bde98e03616e62 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:36:09 +0100
Subject: [PATCH 12/17] fix(phpstan): ajax - improve null checking and function
 existence verification

Changes include:

1) In `removePos.php`, removed the usage of null safe method call, as it was not needed.
2) In `getOrderControl.php`, added a null guard before trying to get view from the OrderProcess and
use it. If the method does not exist, null will be assigned to `$View`.
3) Removed unnecessary fallback to get the first step in `getStep.php`. The current step is enough.
4) In `savePayment.php` added a check for the existence of 'savePayment' method before invoking it
to avoid possible errors.
5) The fallback to get the first step was also removed in `reload.php`.
6) Removed an unnecessary if condition in `send.php` and directly assigned current step's name to
`$current`.
7) In `setQuantity.php`, added a verification to check the existence of 'setQuantity' method before
calling it.

Related: quiqqer/order#172
---
 ajax/frontend/basket/removePos.php             | 2 +-
 ajax/frontend/order/getOrderControl.php        | 7 ++++++-
 ajax/frontend/order/getStep.php                | 5 -----
 ajax/frontend/order/processing/savePayment.php | 7 ++++---
 ajax/frontend/order/reload.php                 | 4 ----
 ajax/frontend/order/send.php                   | 6 +-----
 ajax/frontend/order/setQuantity.php            | 2 +-
 7 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/ajax/frontend/basket/removePos.php b/ajax/frontend/basket/removePos.php
index 4320d813..43c1a414 100644
--- a/ajax/frontend/basket/removePos.php
+++ b/ajax/frontend/basket/removePos.php
@@ -15,7 +15,7 @@
     function ($basketId, $pos) {
         $User = QUI::getUserBySession();
         $Basket = new QUI\ERP\Order\Basket\Basket($basketId, $User);
-        $Basket->getProducts()?->removePos($pos);
+        $Basket->getProducts()->removePos($pos);
 
         QUI::getEvents()->fireEvent(
             'quiqqerOrderBasketRemovePos',
diff --git a/ajax/frontend/order/getOrderControl.php b/ajax/frontend/order/getOrderControl.php
index 0c8b7884..1cfc1d74 100644
--- a/ajax/frontend/order/getOrderControl.php
+++ b/ajax/frontend/order/getOrderControl.php
@@ -20,10 +20,15 @@ function ($orderHash) {
         $Output = new QUI\Output();
         $result = $OrderProcess->create();
         $css = QUI\Control\Manager::getCSS();
+        $View = null;
+
+        if (method_exists($OrderProcess->getOrder(), 'getView')) {
+            $View = $OrderProcess->getOrder()->getView();
+        }
 
         return [
             'html' => $Output->parse($css . $result),
-            'data' => $OrderProcess->getOrder()->getView()->toArray()
+            'data' => $View?->toArray()
         ];
     },
     ['orderHash']
diff --git a/ajax/frontend/order/getStep.php b/ajax/frontend/order/getStep.php
index b7cd5c68..88b40917 100644
--- a/ajax/frontend/order/getStep.php
+++ b/ajax/frontend/order/getStep.php
@@ -28,11 +28,6 @@ function ($orderId, $step, $orderHash, $basketEditable) {
             ]);
 
             $Current = $OrderProcess->getCurrentStep();
-
-            if (!$Current) {
-                $Current = $OrderProcess->getFirstStep();
-            }
-
             $OrderProcess->setAttribute('step', $Current->getName());
 
             $html = $OrderProcess->create();
diff --git a/ajax/frontend/order/processing/savePayment.php b/ajax/frontend/order/processing/savePayment.php
index 05059593..f44b1511 100644
--- a/ajax/frontend/order/processing/savePayment.php
+++ b/ajax/frontend/order/processing/savePayment.php
@@ -22,12 +22,13 @@ function ($orderHash, $payment) {
             'step' => $Processing->getName()
         ]);
 
-        /* @var $Processing Processing */
         $Processing = $OrderProcess->getCurrentStep();
         $Order = $OrderProcess->getOrder();
-
         $Processing->setAttribute('Order', $Order);
-        $Processing->savePayment($payment);
+
+        if (method_exists($Processing, 'savePayment')) {
+            $Processing->savePayment($payment);
+        }
     },
     ['orderHash', 'payment']
 );
diff --git a/ajax/frontend/order/reload.php b/ajax/frontend/order/reload.php
index 16b8c12b..80021bd3 100644
--- a/ajax/frontend/order/reload.php
+++ b/ajax/frontend/order/reload.php
@@ -25,10 +25,6 @@ function ($orderId, $step, $orderHash, $basketEditable) {
         $Order = $OrderProcess->getOrder();
         $Current = $OrderProcess->getCurrentStep();
 
-        if (!$Current) {
-            $Current = $OrderProcess->getFirstStep();
-        }
-
         $OrderProcess->setAttribute('step', $Current->getName());
         $OrderProcess->setAttribute('orderHash', $Order->getUUID());
 
diff --git a/ajax/frontend/order/send.php b/ajax/frontend/order/send.php
index 9779b71f..edbd4142 100644
--- a/ajax/frontend/order/send.php
+++ b/ajax/frontend/order/send.php
@@ -32,11 +32,7 @@ function ($current, $orderHash, $formData) {
             ]);
 
             $result = $OrderProcess->create();
-            $current = false;
-
-            if ($OrderProcess->getCurrentStep()) {
-                $current = $OrderProcess->getCurrentStep()->getName();
-            }
+            $current = $OrderProcess->getCurrentStep()->getName();
 
             return [
                 'html' => $result,
diff --git a/ajax/frontend/order/setQuantity.php b/ajax/frontend/order/setQuantity.php
index 7ef1f249..885045dd 100644
--- a/ajax/frontend/order/setQuantity.php
+++ b/ajax/frontend/order/setQuantity.php
@@ -30,7 +30,7 @@ function ($orderHash, $pos, $quantity) {
         $Products = $Basket->getProducts();
         $products = $Products->getProducts(); // get as array
 
-        if (isset($products[$pos])) {
+        if (isset($products[$pos]) && method_exists($products[$pos], 'setQuantity')) {
             $products[$pos]->setQuantity($quantity);
         }
 
-- 
GitLab


From d2626882f28d253f7b20796be6c42cca0f6f0cf8 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:39:10 +0100
Subject: [PATCH 13/17] style: correct typo in comments

Fixed a typo in the comment of `getEntityTypeTitle` method in `OutputProviderOrder.php` file. The
word "ommitted" is replaced with "omitted".
---
 src/QUI/ERP/Order/Output/OutputProviderOrder.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/QUI/ERP/Order/Output/OutputProviderOrder.php b/src/QUI/ERP/Order/Output/OutputProviderOrder.php
index 5e887cff..dab5709c 100644
--- a/src/QUI/ERP/Order/Output/OutputProviderOrder.php
+++ b/src/QUI/ERP/Order/Output/OutputProviderOrder.php
@@ -54,7 +54,7 @@ public static function getEntityType(): string
     /**
      * Get title for the output entity
      *
-     * @param Locale|null $Locale $Locale (optional) - If ommitted use \QUI::getLocale()
+     * @param Locale|null $Locale $Locale (optional) - If omitted use \QUI::getLocale()
      * @return string
      */
     public static function getEntityTypeTitle(null | Locale $Locale = null): string
-- 
GitLab


From 2f717949c4117a9b423fdb823bf2d32885d9022b Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:41:11 +0100
Subject: [PATCH 14/17] style(phpstan): improve code readability in
 OutputProviderOrder

Rearranged conditional statement checks for better readability. This involves the check for whether
the class 'QUI\\ERP\\Payments\\SEPA\\Provider' exists and if 'quiqqer/payment-sepa' package is
installed.
---
 src/QUI/ERP/Order/Output/OutputProviderOrder.php | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/QUI/ERP/Order/Output/OutputProviderOrder.php b/src/QUI/ERP/Order/Output/OutputProviderOrder.php
index dab5709c..f853082b 100644
--- a/src/QUI/ERP/Order/Output/OutputProviderOrder.php
+++ b/src/QUI/ERP/Order/Output/OutputProviderOrder.php
@@ -474,9 +474,10 @@ protected static function getEpcQrCodeImageImgSrc(Order $Order): bool | string
 
 
         // Prefer bank account set in SEPA module if available
-        if (class_exists('QUI\ERP\Payments\SEPA\Provider') && QUI::getPackageManager()->isInstalled(
-                'quiqqer/payment-sepa'
-            )) {
+        if (
+            class_exists('QUI\ERP\Payments\SEPA\Provider')
+            && QUI::getPackageManager()->isInstalled('quiqqer/payment-sepa')
+        ) {
             $creditorBankAccount = QUI\ERP\Payments\SEPA\Provider::getCreditorBankAccount();
         } else {
             $creditorBankAccount = BankAccounts::getCompanyBankAccount();
-- 
GitLab


From 082aef606fdde66e3000da33172bbc6ed9726651 Mon Sep 17 00:00:00 2001
From: Henning <leutz@pcsg.de>
Date: Sun, 23 Feb 2025 10:53:45 +0100
Subject: [PATCH 15/17] chore(phpstan): ignore phpstan errors due to missing
 classes

Ignored various PHPStan errors in 'phpstan-baseline.neon' file due to missing classes and methods.
Many of these errors were related to the ERP, Shipping, and Invoice modules. This fix suppresses
the error reporting to ensure smooth operation of the rest of the code base. However, it's
recommended to address these missing dependencies for a long-term solution.
---
 phpstan-baseline.neon | 219 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 219 insertions(+)

diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index e69de29b..87f432c1 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -0,0 +1,219 @@
+parameters:
+    ignoreErrors:
+        -
+            message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: ajax/backend/createInvoice.php
+        -
+            message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: ajax/backend/createInvoice.php
+        -
+            message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
+            path: ajax/backend/createSalesOrder.php
+        -
+            message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: ajax/backend/post.php
+        -
+            message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: ajax/backend/post.php
+        -
+            message: "#^Property QUI\\\\ERP\\\\Order\\\\AbstractOrder::\\$ShippingStatus has unknown class QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status as its type\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Call to method getType\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Call to method getType\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\AbstractOrder::getShipping\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\AbstractOrder::setShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Call to method getId\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\AbstractOrder::validateShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Call to method setErpEntity\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Call to method isValid\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Call to method canUsedInErpEntity\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Call to method canUsedBy\\(\\) on an unknown class QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\AbstractOrder::getShippingStatus\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Parameter \\$status of method QUI\\\\ERP\\\\Order\\\\AbstractOrder::setShippingStatus\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\.$#"
+            path: src/QUI/ERP/Order/AbstractOrder.php
+        -
+            message: "#^Class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary not found\\.$#"
+            path: src/QUI/ERP/Order/Controls/Order/Order.php
+        -
+            message: "#^Parameter \\$InvoiceTemporary of method QUI\\\\ERP\\\\Order\\\\EventHandling::onQuiqqerInvoiceTemporaryInvoicePostEnd\\(\\) has invalid type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/EventHandling.php
+        -
+            message: "#^Parameter \\$Invoice of method QUI\\\\ERP\\\\Order\\\\EventHandling::onQuiqqerInvoiceTemporaryInvoicePostEnd\\(\\) has invalid type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/EventHandling.php
+        -
+            message: "#^Parameter \\$SalesOrder of method QUI\\\\ERP\\\\Order\\\\EventHandling::onQuiqqerSalesOrdersSaveEnd\\(\\) has invalid type QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
+            path: src/QUI/ERP/Order/EventHandling.php
+        -
+            message: "#^Call to method getData\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
+            path: src/QUI/ERP/Order/EventHandling.php
+        -
+            message: "#^Call to method getShipping\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
+            path: src/QUI/ERP/Order/EventHandling.php
+        -
+            message: "#^Call to method getShippingStatus\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
+            path: src/QUI/ERP/Order/EventHandling.php
+        -
+            message: "#^Call to static method getInstance\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Handler\\.$#"
+            path: src/QUI/ERP/Order/EventHandling.php
+        -
+            message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOpenedOrders.php
+        -
+            message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOpenedOrders.php
+        -
+            message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
+        -
+            message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\Order::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\Order::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\|QUI\\\\Exception is not subtype of Throwable$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Call to static method getInstance\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Handler\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Instantiated class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception not found\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Throwing object of an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\Order::createInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\Order::createInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Call to static method addressRequirement\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Utils\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Call to static method addressRequirementThreshold\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Utils\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Call to static method getInstance\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Factory\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\Order::createSalesOrder\\(\\) has invalid return type QUI\\\\ERP\\\\SalesOrders\\\\SalesOrder\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Call to static method createSalesOrder\\(\\) on an unknown class QUI\\\\ERP\\\\SalesOrders\\\\Handler\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\Order::post\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\Order::post\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/Order.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInProcess::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/OrderInProcess.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInProcess::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/OrderInProcess.php
+        -
+            message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\|QUI\\\\Exception is not subtype of Throwable$#"
+            path: src/QUI/ERP/Order/OrderInProcess.php
+        -
+            message: "#^Instantiated class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception not found\\.$#"
+            path: src/QUI/ERP/Order/OrderInProcess.php
+        -
+            message: "#^Throwing object of an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\.$#"
+            path: src/QUI/ERP/Order/OrderInProcess.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInterface::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/OrderInterface.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInterface::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/OrderInterface.php
+        -
+            message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception is not subtype of Throwable$#"
+            path: src/QUI/ERP/Order/OrderInterface.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderInterface::getShipping\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
+            path: src/QUI/ERP/Order/OrderInterface.php
+        -
+            message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\OrderInterface::setShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/OrderInterface.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView::getShippingStatus\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\ShippingStatus\\\\Status\\.$#"
+            path: src/QUI/ERP/Order/OrderView.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/OrderView.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView::getInvoice\\(\\) has invalid return type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/OrderView.php
+        -
+            message: "#^PHPDoc tag @throws with type QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Exception\\|QUI\\\\Exception is not subtype of Throwable$#"
+            path: src/QUI/ERP/Order/OrderView.php
+        -
+            message: "#^Parameter \\$Shipping of method QUI\\\\ERP\\\\Order\\\\OrderView::setShipping\\(\\) has invalid type QUI\\\\ERP\\\\Shipping\\\\Api\\\\ShippingInterface\\.$#"
+            path: src/QUI/ERP/Order/OrderView.php
+        -
+            message: "#^Method QUI\\\\ERP\\\\Order\\\\OrderView::getShipping\\(\\) has invalid return type QUI\\\\ERP\\\\Shipping\\\\Types\\\\ShippingEntry\\.$#"
+            path: src/QUI/ERP/Order/OrderView.php
+        -
+            message: "#^Instantiated class chillerlan\\\\QRCode\\\\QROptions not found\\.$#"
+            path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
+        -
+            message: "#^Access to constant VERSION_AUTO on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
+            path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
+        -
+            message: "#^Access to constant OUTPUT_IMAGE_PNG on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
+            path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
+        -
+            message: "#^Access to constant ECC_M on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
+            path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
+        -
+            message: "#^Instantiated class chillerlan\\\\QRCode\\\\QRCode not found\\.$#"
+            path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
+        -
+            message: "#^Call to method render\\(\\) on an unknown class chillerlan\\\\QRCode\\\\QRCode\\.$#"
+            path: src/QUI/ERP/Order/Output/OutputProviderOrder.php
+        -
+            message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/Search.php
+        -
+            message: "#^Call to method getUUID\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/Search.php
+        -
+            message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Invoice\\.$#"
+            path: src/QUI/ERP/Order/Search.php
+        -
+            message: "#^Call to method getAttribute\\(\\) on an unknown class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\InvoiceTemporary\\.$#"
+            path: src/QUI/ERP/Order/Search.php
+        -
+            message: "#^Class QUI\\\\ERP\\\\Accounting\\\\Invoice\\\\Articles\\\\Text not found\\.$#"
+            path: src/QUI/ERP/Order/Utils/Utils.php
+            
\ No newline at end of file
-- 
GitLab


From 21a7e57ea9e6387df1befb1190319044d4f1c6fa Mon Sep 17 00:00:00 2001
From: Michael Danielczok <michael@pcsg.de>
Date: Mon, 24 Feb 2025 14:22:57 +0100
Subject: [PATCH 16/17] fix: adjust order in user profile

Related: quiqqer/template-cologne#119
---
 bin/frontend/controls/frontendusers/Orders.js |  27 ++-
 locale.xml                                    |  42 +++-
 settings.xml                                  |  41 ++++
 .../Controls/UserOrders.Article.html          |  97 ++++----
 .../Controls/UserOrders.Order.html            | 127 +++++-----
 .../FrontendUsers/Controls/UserOrders.css     | 219 ++++++++----------
 .../FrontendUsers/Controls/UserOrders.html    |  56 ++---
 .../FrontendUsers/Controls/UserOrders.php     |   5 +
 8 files changed, 353 insertions(+), 261 deletions(-)

diff --git a/bin/frontend/controls/frontendusers/Orders.js b/bin/frontend/controls/frontendusers/Orders.js
index 431ebc22..760eef85 100644
--- a/bin/frontend/controls/frontendusers/Orders.js
+++ b/bin/frontend/controls/frontendusers/Orders.js
@@ -63,9 +63,10 @@ define('package/quiqqer/order/bin/frontend/controls/frontendusers/Orders', [
          */
         $onImport: function () {
             var self = this,
-                Elm  = this.getElm();
+                Elm  = this.getElm(),
+            SectionContainer = Elm.querySelector('[data-ref="section-container"]');
 
-            this.$List = Elm.getElement('.quiqqer-order-profile-orders-list');
+            this.$List = Elm.getElement('[data-ref="order-list"]');
 
             this.$OrderContainer = new Element('div', {
                 'class': 'quiqqer-order-profile-orders-order-container',
@@ -74,9 +75,16 @@ define('package/quiqqer/order/bin/frontend/controls/frontendusers/Orders', [
                     opacity : 0,
                     position: 'relative'
                 }
-            }).inject(this.getElm());
+            });
+
+            if (SectionContainer) {
+                this.$OrderContainer.inject(SectionContainer);
+                this.Loader.inject(SectionContainer);
+            } else {
+                this.$OrderContainer.inject(Elm);
+                this.Loader.inject(Elm);
+            }
 
-            this.Loader.inject(Elm);
             this.$setEvents();
 
             // pagination events
@@ -179,6 +187,11 @@ define('package/quiqqer/order/bin/frontend/controls/frontendusers/Orders', [
                         onLoad: function () {
                             self.Loader.hide();
                             self.$hideList().then(function () {
+                                self.$OrderContainer.scrollIntoView({
+                                    behavior: "smooth",
+                                    block: "start"
+                                });
+
                                 return self.$showOrderContainer();
                             });
                         }
@@ -245,9 +258,7 @@ define('package/quiqqer/order/bin/frontend/controls/frontendusers/Orders', [
          */
         $setEvents: function () {
             var self       = this;
-            var orderLinks = this.getElm().getElements(
-                '.quiqqer-order-profile-orders-order-header-orderId a'
-            );
+            var orderLinks = this.getElm().getElements('[data-ref="order-link"]');
 
             orderLinks.addEvent('click', function (event) {
                 var Target = event.target;
@@ -298,6 +309,7 @@ define('package/quiqqer/order/bin/frontend/controls/frontendusers/Orders', [
             );
 
             elements.push(self.$List);
+            elements.push(...this.getElm().querySelectorAll('[data-ref="order-text"]'))
 
             return new Promise(function (resolve) {
                 elements.setStyle('position', 'relative');
@@ -328,6 +340,7 @@ define('package/quiqqer/order/bin/frontend/controls/frontendusers/Orders', [
             );
 
             elements.push(self.$List);
+            elements.push(...this.getElm().querySelectorAll('[data-ref="order-text"]'))
 
             elements.setStyle('display', null);
 
diff --git a/locale.xml b/locale.xml
index 16fda9b3..1d2c6178 100644
--- a/locale.xml
+++ b/locale.xml
@@ -357,10 +357,18 @@
             <de><![CDATA[Meine Bestellungen]]></de>
             <en><![CDATA[My orders]]></en>
         </locale>
+        <locale name="control.frontendUsers.orders.title">
+            <de><![CDATA[Bestellungen]]></de>
+            <en><![CDATA[Orders]]></en>
+        </locale>
         <locale name="profile.opened.orders.title">
-            <de><![CDATA[Meine offene Bestellungen]]></de>
+            <de><![CDATA[Meine offenen Bestellungen]]></de>
             <en><![CDATA[My open orders]]></en>
         </locale>
+        <locale name="control.frontendUsers.opened.orders.title">
+            <de><![CDATA[Offene Bestellungen]]></de>
+            <en><![CDATA[Open orders]]></en>
+        </locale>
         <locale name="message.orders.panel.empty.articles">
             <de><![CDATA[Die Bestellung besitzt keine Artikel.]]></de>
             <en><![CDATA[The order does not own any articles.]]></en>
@@ -833,6 +841,28 @@
             <de><![CDATA[Vorgehen bei gescheiterter Zahlung]]></de>
             <en><![CDATA[Procedure for failed payment]]></en>
         </locale>
+
+        <locale name="order.settings.userProfile.title">
+            <de><![CDATA[Benutezrprofil]]></de>
+            <en><![CDATA[User profile]]></en>
+        </locale>
+        <locale name="order.settings.userProfile.showArticleImage">
+            <de><![CDATA[Artikelbilder anzeigen]]></de>
+            <en><![CDATA[Show article images]]></en>
+        </locale>
+        <locale name="order.settings.userProfile.showArticleImage.desc">
+            <de><![CDATA[Wenn aktiviert, werden Artikelbilder im Benutzerprofil im Bereich "Bestellungen" und "Offene Bestellungen" angezeigt.]]></de>
+            <en><![CDATA[When enabled, product images are displayed in the user profile's order history and open orders section.]]></en>
+        </locale>
+        <locale name="order.settings.userProfile.disableProductLinks">
+            <de><![CDATA[Keine Prodeuktlinks]]></de>
+            <en><![CDATA[Disable product links]]></en>
+        </locale>
+        <locale name="order.settings.userProfile.disableProductLinks.desc">
+            <de><![CDATA[Wenn aktiviert, werden keine Links zu den Produkten im Benutzerprofil angezeigt.]]></de>
+            <en><![CDATA[When enabled, no links to products will be displayed in the user profile.]]></en>
+        </locale>
+
         <locale name="order.settings.mails.attachments">
             <de><![CDATA[Automatische Mailanhänge]]></de>
             <en><![CDATA[Automatic mail attachments]]></en>
@@ -1090,10 +1120,18 @@
             <de><![CDATA[Bestellstatus]]></de>
             <en><![CDATA[Order status]]></en>
         </locale>
-        <locale name="control.profile.orders.order.invoice">
+        <locale name="control.profile.orders.order.invoice.label">
             <de><![CDATA[Rechnung]]></de>
             <en><![CDATA[Invoice]]></en>
         </locale>
+        <locale name="control.profile.orders.order.invoice">
+            <de><![CDATA[Rechnung herunterladen]]></de>
+            <en><![CDATA[Download invoice]]></en>
+        </locale>
+        <locale name="control.profile.orders.order.continuePayment.label">
+            <de><![CDATA[Benötigte Aktion]]></de>
+            <en><![CDATA[Required action]]></en>
+        </locale>
         <locale name="control.profile.orders.order.continuePayment">
             <de><![CDATA[Bezahlung fortführen]]></de>
             <en><![CDATA[Continue payment]]></en>
diff --git a/settings.xml b/settings.xml
index 7e481a0f..bfabc705 100644
--- a/settings.xml
+++ b/settings.xml
@@ -37,6 +37,17 @@
                 </conf>
             </section>
 
+            <section name="userProfile">
+                <conf name="showArticleImage">
+                    <type><![CDATA[bool]]></type>
+                    <defaultvalue><![CDATA[1]]></defaultvalue>
+                </conf>
+                <conf name="disableProductLinks">
+                    <type><![CDATA[bool]]></type>
+                    <defaultvalue><![CDATA[0]]></defaultvalue>
+                </conf>
+            </section>
+
             <section name="mails">
                 <!-- Datenschutz -->
                 <conf name="privacyPolicy">
@@ -234,6 +245,36 @@
                         </input>
                     </settings>
 
+                    <settings>
+                        <title>
+                            <locale group="quiqqer/order" var="order.settings.userProfile.title"/>
+                        </title>
+
+                        <input type="checkbox" conf="userProfile.showArticleImage">
+                            <text>
+                                <locale group="quiqqer/order"
+                                        var="order.settings.userProfile.showArticleImage"/>
+                            </text>
+                            <description>
+                                <locale group="quiqqer/order"
+                                        var="order.settings.userProfile.showArticleImage.desc"
+                                />
+                            </description>
+                        </input>
+
+                        <input type="checkbox" conf="userProfile.disableProductLinks">
+                            <text>
+                                <locale group="quiqqer/order"
+                                        var="order.settings.userProfile.disableProductLinks"/>
+                            </text>
+                            <description>
+                                <locale group="quiqqer/order"
+                                        var="order.settings.userProfile.disableProductLinks.desc"
+                                />
+                            </description>
+                        </input>
+                    </settings>
+
                     <settings>
                         <title>
                             <locale group="quiqqer/order" var="order.settings.mails.attachments"/>
diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Article.html b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Article.html
index 9510f065..9bb19e3e 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Article.html
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Article.html
@@ -1,52 +1,65 @@
 <article class="quiqqer-order-profile-orders-order-articles-article"
          data-qui="package/quiqqer/order/bin/frontend/controls/frontendusers/Article"
 >
-    <div class="quiqqer-order-profile-orders-order-articles-image">
-        {if !empty($Image)}
-        {image image=$Image width="200" height=200}
-        {else}
-        {image image=$Project->getMedia()->getPlaceholderImage()}
-        {/if}
-    </div>
+    {if $showImage}
+        <div class="quiqqer-order-profile-orders-order-articles-image">
+            {if !$noLink && !empty($Product) && $Product->getUrl()}
+            <a href="{$Product->getUrl()}"
+               class="quiqqer-order-profile-orders-order-articles-image__link"
+               target="_blank"
+            >
+                {/if}
+                {if !empty($Image)}
+                    {image image=$Image width="200" height=200}
+                {else}
+                    {image image=$Project->getMedia()->getPlaceholderImage()}
+                {/if}
+                {if !$noLink && !empty($Product) && $Product->getUrl()}
+            </a>
+            {/if}
+        </div>
+    {/if}
 
-    <div class="quiqqer-order-profile-orders-order-articles-information">
-        {if !empty($Product)}
-        <a href="{$Product->getUrl()}"
-           class="quiqqer-order-profile-orders-order-articles-title"
-           target="_blank"
-        >
-            {$Article->getTitle()}
-        </a>
-        {else}
-        <div class="quiqqer-order-profile-orders-order-articles-title">
-            {$Article->getTitle()}
+    <div class="quiqqer-order-profile-orders-order-articles-data">
+        <div class="quiqqer-order-profile-orders-order-articles-information">
+            {if !$noLink &&!empty($Product)}
+                <a href="{$Product->getUrl()}"
+                   class="quiqqer-order-profile-orders-order-articles-title"
+                   target="_blank"
+                >
+                    {$Article->getTitle()}
+                </a>
+            {else}
+                <div class="quiqqer-order-profile-orders-order-articles-title">
+                    {$Article->getTitle()}
+                </div>
+            {/if}
+
+            <div class="quiqqer-order-profile-orders-order-articles-description">
+                {$Article->getDescription()}
+            </div>
         </div>
-        {/if}
 
-        <div class="quiqqer-order-profile-orders-order-articles-description">
-            {$Article->getDescription()}
+        <div class="quiqqer-order-profile-orders-order-articles-price">
+            {$Article->getPrice()->getDisplayPrice()}
         </div>
-    </div>
 
-    <div class="quiqqer-order-profile-orders-order-articles-price">
-        {$Article->getPrice()->getDisplayPrice()}
+        <div class="quiqqer-order-profile-orders-order-articles-buttons">
+            {if !empty($Product) && $Product->isActive()}
+                <noscript>
+                    <style>
+                        .quiqqer-order-profile-orders-order-articles-rebuy {
+                            display: none
+                        }
+                    </style>
+                </noscript>
+                <button class="quiqqer-order-profile-orders-order-articles-rebuy btn btn-primary"
+                        data-articleno="{$Article->getArticleNo()}"
+                        disabled
+                >
+                    {locale group="quiqqer/order" var="controls.UsedOrders.Article.buy_again"}
+                </button>
+            {/if}
+        </div>
     </div>
-
-    {if !empty($Product) && $Product->isActive()}
-    <noscript>
-        <style>
-            .quiqqer-order-profile-orders-order-articles-rebuy {
-                display: none
-            }
-        </style>
-    </noscript>
-    <button class="quiqqer-order-profile-orders-order-articles-rebuy"
-            data-articleno="{$Article->getArticleNo()}"
-            disabled
-    >
-        {locale group="quiqqer/order" var="controls.UsedOrders.Article.buy_again"}
-    </button>
-    {/if}
-
-    <div class="quiqqer-order-profile-orders-order-articles-buttons"></div>
 </article>
diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html
index 662a7fd2..120f9eae 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html
@@ -1,81 +1,96 @@
 <section class="quiqqer-order-profile-orders-order">
-    <header>
-        <div class="quiqqer-order-profile-orders-order-header-date">
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.date"}</span>
-            <span>{$Order->getCreateDate()}</span>
+    <header class="quiqqer-order-profile-orders-order__header">
+        <div class="quiqqer-order-profile-orders-order__date">
+            <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/order" var="control.profile.orders.order.date"}</span>
+            <div class="quiqqer-order-profile-orders-order__value">{$Order->getCreateDate()}</div>
         </div>
 
-        <div class="quiqqer-order-profile-orders-order-header-total">
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.total"}</span>
-            <span>{$order.calculations.display_sum}</span>
-        </div>
-
-        <div class="quiqqer-order-profile-orders-order-header-addressInvoice">
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.invoiceAddress"}</span>
-            {if $Invoice}
-            {assign var=Customer value=$Invoice->getCustomer()}
-            {else}
-            {assign var=Customer value=$Order->getCustomer()}
-            {/if}
-
-            {assign var=Address value=$Customer->getAddress()}
-            {$Address->render(['tel' => false, 'mail' => false])}
-            <span>
-                <span>{$Address->getName()}</span>
-                <span class="fa fa-angle-down"></span>
-            </span>
-        </div>
-
-        <div class="quiqqer-order-profile-orders-order-header-orderId">
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.orderNo"}</span>
-            <a href="{$Utils->getOrderUrl($Project, $Order)}"
-               target="_blank"
-               data-hash="{$Order->getHash()}"
-               title="{locale group='quiqqer/order' var='control.order.details.title'}"
-            >
-                {$Order->getPrefixedId()}
-            </a>
+        <div class="quiqqer-order-profile-orders-order__orderId">
+            <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/order" var="control.profile.orders.order.orderNo"}</span>
+            <div class="quiqqer-order-profile-orders-order__value">
+                <a href="{$Utils->getOrderUrl($Project, $Order)}"
+                   target="_blank"
+                   data-ref="order-link"
+                   data-hash="{$Order->getHash()}"
+                   title="{locale group='quiqqer/order' var='control.order.details.title'}"
+                >
+                    {$Order->getPrefixedId()}
+                </a>
+            </div>
         </div>
     </header>
 
     <div class="quiqqer-order-profile-orders-order-articles">
         {foreach $articles as $Article}
-        {$this->renderArticle($Article)}
+            {$this->renderArticle($Article)}
         {/foreach}
     </div>
 
-    <footer>
+    <footer class="quiqqer-order-profile-orders-order__footer">
         {if $Order->isPosted()}
-        <a href="{$Order->getAttribute('downloadLink')}" target="_blank">
-            <span class="fa fa-file-pdf-o"></span>
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.invoice"}</span>
-        </a>
+        <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-invoice">
+            <span class="quiqqer-order-profile-orders-order__label">
+                {locale group="quiqqer/order" var="control.profile.orders.order.invoice.label"}
+            </span>
+            <div class="quiqqer-order-profile-orders-order__value">
+                <a href="{$Order->getAttribute('downloadLink')}" target="_blank">
+                    <span class="fa fa-file-pdf-o"></span>
+                    <span>{locale group="quiqqer/order" var="control.profile.orders.order.invoice"}</span>
+                </a>
+            </div>
+        </div>
         {else if !$Order->isSuccessful()}
-        <a href="{$orderUrl}" target="_blank" class="">
-            <span class="fa fa-shopping-basket"></span>
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.continuePayment"}</span>
-        </a>
+        <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-continuePayment">
+            <span class="quiqqer-order-profile-orders-order__label">
+                {locale group="quiqqer/order" var="control.profile.orders.order.continuePayment.label"}
+            </span>
+            <div class="quiqqer-order-profile-orders-order__value">
+                <a href="{$orderUrl}" target="_blank">
+                    <span class="fa fa-shopping-basket"></span>
+                    <span>{locale group="quiqqer/order" var="control.profile.orders.order.continuePayment"}</span>
+                </a>
+            </div>
+        </div>
         {/if}
 
-        {if $Payment}
-        <div class="quiqqer-order-profile-orders-order-footer-paymentType">
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.paymentMethod"}:</span>
-            <span>{$Payment->getTitle()}</span>
+        <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-total">
+            <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/order" var="control.profile.orders.order.total"}</span>
+            <div class="quiqqer-order-profile-orders-order__value">{$order.calculations.display_sum}</div>
         </div>
+
+        <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-addressInvoice">
+            <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/order" var="control.profile.orders.order.invoiceAddress"}</span>
+            {if $Invoice}
+                {assign var=Customer value=$Invoice->getCustomer()}
+            {else}
+                {assign var=Customer value=$Order->getCustomer()}
+            {/if}
+
+            {assign var=Address value=$Customer->getAddress()}
+            <div class="quiqqer-order-profile-orders-order__value">
+                {$Address->render(['tel' => false, 'mail' => false])}
+            </div>
+        </div>
+
+        {if $Payment}
+            <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-paymentType">
+                <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/order" var="control.profile.orders.order.paymentMethod"}:</span>
+                <div class="quiqqer-order-profile-orders-order__value">{$Payment->getTitle()}</div>
+            </div>
         {/if}
 
         {if !empty($shippingStatus)}
-        <div class="quiqqer-order-profile-orders-order-footer-shipping">
-            <span>{locale group="quiqqer/shipping" var="control.profile.orders.shipping"}:</span>
-            <span>{$shippingStatus}</span>
-        </div>
+            <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-footer-shipping">
+                <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/shipping" var="control.profile.orders.shipping"}:</span>
+                <div class="quiqqer-order-profile-orders-order__value">{$shippingStatus}</div>
+            </div>
         {/if}
 
         {if isset($orderStatus)}
-        <div class="quiqqer-order-profile-orders-order-footer-orderStatus">
-            <span>{locale group="quiqqer/order" var="control.profile.orders.order.orderStatus"}:</span>
-            <span>{$orderStatus}</span>
-        </div>
+            <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-footer-orderStatus">
+                <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/order" var="control.profile.orders.order.orderStatus"}:</span>
+                <div class="quiqqer-order-profile-orders-order__value">{$orderStatus}</div>
+            </div>
         {/if}
     </footer>
 </section>
diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css
index 4c8b1018..ad0c4a21 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css
@@ -1,110 +1,122 @@
-.quiqqer-order-profile-orders,
-.quiqqer-order-profile-orders-list {
-    float: left;
-    width: 100%;
+.quiqqer-frontendUsers-section--userOrders {
+    --_label-color: var(--label-color, #999);
+    --_label-fontSize: var(--label-fontSize, 0.875rem);
+    --_box-padding: var(--box-padding, 0.75rem);
+    --_box-bgColor: var(--box-bgColor, #f6f6f6);
+    --_borderColor: var(--borderColor, #ddd);
+    --_borderWidth: var(--borderWidth, 1px);
+    --_scrollMarginTop: var(--scrollMarginTop,var(--_qui-template-scrollMarginTop, 0px));
 }
 
-/** One Order
- =============================================== */
-
-.quiqqer-order-profile-orders-order {
-    border: 1px #ddd solid;
-    clear: both;
-    float: left;
-    margin-bottom: 10px;
-    width: 100%;
+.quiqqer-order-profile-orders-list {
+    display: grid;
+    grid-template-columns: 1fr;
+    gap: 2rem;
 }
 
-.quiqqer-order-profile-orders-order header {
-    background: #f6f6f6;
-    border-bottom: 1px #ddd solid;
-    float: left;
-    padding: 10px;
-    width: 100%;
+:where(.quiqqer-order-profile-orders-order__label) {
+    color: var(--_label-color);
+    font-size: var(--_label-fontSize);
 }
 
-.quiqqer-order-profile-orders-order-header-date,
-.quiqqer-order-profile-orders-order-header-total,
-.quiqqer-order-profile-orders-order-header-addressInvoice,
-.quiqqer-order-profile-orders-order-header-addressDelivery {
-    float: left;
-    position: relative;
-    width: 25%;
+/* header */
+:where(.quiqqer-order-profile-orders-order__header) {
+    background: var(--_box-bgColor);
+    border-bottom: var(--_borderWidth) solid var(--_borderColor);
+    padding: var(--_box-padding);
+    display: flex;
+    justify-content: space-between;
 }
 
-.quiqqer-order-profile-orders-order-header-date span,
-.quiqqer-order-profile-orders-order-header-total span,
-.quiqqer-order-profile-orders-order-header-addressInvoice span,
-.quiqqer-order-profile-orders-order-header-addressDelivery span {
-    clear: both;
-    float: left;
+:where(.quiqqer-order-profile-orders-order__header .quiqqer-order-profile-orders-order__orderId) {
+    text-align: right;
 }
 
-.quiqqer-order-profile-orders-order-header-addressInvoice {
-    cursor: pointer;
-}
+/** One Order
+ =============================================== */
 
-.quiqqer-order-profile-orders-order-header-addressInvoice address {
-    cursor: default;
-    display: none;
-    background: #ffffff;
-    border: 1px #ddd solid;
-    left: 0;
-    top: 35px;
-    padding: 10px;
-    position: absolute;
-    width: 100%;
+:where(.quiqqer-order-profile-orders-order) {
+    container-type: inline-size;
+    container-name: quiqqer-order-profile-orders-order;
+
+    border: var(--_borderWidth) solid var(--_borderColor);
+    min-width: 0;
 }
 
-.quiqqer-order-profile-orders-order-header-addressInvoice:is(:hover, :active) address {
-    display: inline-block;
+/* article list */
+.quiqqer-order-profile-orders-order-articles {
+    padding: var(--_box-padding);
+    display: grid;
+    gap: 1rem;
 }
 
-.quiqqer-order-profile-orders-order-header-addressInvoice span {
-    text-align: left;
+/* single article */
+.quiqqer-order-profile-orders-order-articles-article {
+    display: flex;
+    gap: 1rem;
+    min-width: 0;
 }
 
-.quiqqer-order-profile-orders-order-articles {
-    float: left;
-    padding: 10px;
-    width: 100%;
+:where(.quiqqer-order-profile-orders-order-articles-image) {
+    width: calc(10rem - 0.5rem);
+    height: calc(10rem - 0.5rem);
+    background: var(--_box-bgColor);
+    border-radius: 0.5rem;
+    overflow: hidden;
+    display: grid;
+    place-content: center;
+    padding: var(--_box-padding);
+    flex-shrink: 0;
 }
 
-.quiqqer-order-profile-orders-order-articles-article {
-    float: left;
-    width: 100%;
+.quiqqer-order-profile-orders-order-articles-data {
+    flex-grow: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 0.5rem;
 }
 
-.quiqqer-order-profile-orders-order-articles-information {
-    padding-top: 10px;
+:where(.quiqqer-order-profile-orders-order-articles-title) {
+    font-weight: bolder;
 }
 
-.quiqqer-order-profile-orders-order-articles-image {
-    float: left;
-    margin-right: 10px;
+.quiqqer-order-profile-orders-order-articles-buttons {
+    margin-top: auto;
 }
 
-.quiqqer-order-profile-orders-order-articles-description {
-    margin: 5px 0;
+/* footer  */
+:where(.quiqqer-order-profile-orders-order__footer) {
+    border-top: var(--_borderWidth) solid var(--_borderColor);
+    padding: var(--_box-padding);
+    display: flex;
+    flex-direction: column;
+    gap: 0.5rem;
 }
 
-.quiqqer-order-profile-orders-order-footer-paymentType {
-    margin-top: 10px;
+:where(.quiqqer-order-profile-orders-order__group) {
+    display: grid;
+    grid-template-columns: 10rem 1fr;
+    gap: 0.5rem;
 }
 
-.quiqqer-order-profile-orders-order footer {
-    background: #f6f6f6;
-    border-top: 1px #ddd solid;
-    float: left;
-    padding: 10px;
-    width: 100%;
+@container quiqqer-order-profile-orders-order (max-width: 25rem) {
+    .quiqqer-order-profile-orders-order-articles-article {
+        flex-direction: column;
+    }
+
+    :where(.quiqqer-order-profile-orders-order-articles-article:not(:first-child)) {
+        border-top: var(--_borderWidth) solid var(--_borderColor);
+        padding-top: 1rem;
+    }
+
+    :where(.quiqqer-order-profile-orders-order__group) {
+        display: block;
+    }
 }
 
 /** Pagination
  =============================================== */
-
 .quiqqer-order-profile-orders-pagination {
-    float: left;
     width: 100%;
 }
 
@@ -112,56 +124,17 @@
     text-align: right;
 }
 
-@media (max-width: 768px) {
-    .quiqqer-order-profile-orders-order-header-date,
-    .quiqqer-order-profile-orders-order-header-total,
-    .quiqqer-order-profile-orders-order-header-addressInvoice,
-    .quiqqer-order-profile-orders-order-header-addressDelivery {
-        width: 100%;
-    }
-
-    .quiqqer-order-profile-orders-order-header-orderId {
-        float: left;
-        margin-top: 10px;
-        width: 100%;
-    }
-
-    .quiqqer-order-profile-orders-order-header-date > span,
-    .quiqqer-order-profile-orders-order-header-total > span,
-    .quiqqer-order-profile-orders-order-header-orderId > span,
-    .quiqqer-order-profile-orders-order-header-orderId > a,
-    .quiqqer-order-profile-orders-order-header-addressInvoice > span {
-        clear: none;
-        float: left;
-        width: 50%;
-    }
-
-    .quiqqer-order-profile-orders-order-header-addressInvoice address {
-        top: 100%;
-        z-index: 1;
-    }
-
-    .quiqqer-order-profile-orders .quiqqer-order-profile-orders-pagination:first-child {
-        margin-bottom: 20px;
-    }
-
-    .quiqqer-order-control-order-information-invoiceAddress,
-    .quiqqer-order-control-order-information-orderData,
-    .quiqqer-order-control-order-information-payment {
-        clear: both;
-        width: 100%;
-    }
+.quiqqer-sheets-mobile {
+    margin-top: 2rem;
+    width: 100%;
+}
 
-    .quiqqer-order-control-order-information-payment-icon {
-        margin-bottom: 10px;
-        max-width: 100%;
-    }
+/* Back btn */
+.quiqqer-order-control-order-backButton {
+    margin-top: 1rem;
+}
 
-    .quiqqer-order-control-order-information-orderData-placeholder td {
-        font-size: 1px;
-        height: 2px;
-        display: block;
-        padding: 0;
-        margin: 0;
-    }
+/* container for order details (open per click on order number) */
+.quiqqer-order-profile-orders-order-container {
+    scroll-margin-top: var(--_scrollMarginTop);
 }
\ No newline at end of file
diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.html b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.html
index 4923344e..ecbb8fec 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.html
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.html
@@ -1,33 +1,27 @@
-{if $sheetsMax && $sheetsMax != 1}
-<div class="quiqqer-order-profile-orders-pagination">
-    {control
-    control="QUI\Controls\Navigating\Pagination"
-    useAjax=true
-    Project=$Project
-    limit=$sheetLimit
-    sheets=$sheetsMax
-    sheet=$sheetCurrent
-    }
-</div>
-{/if}
+<section class="quiqqer-frontendUsers-profile-section quiqqer-frontendUsers-section--userOrders" data-ref="section-container">
+    <div data-ref="order-text">
+        <h2>{locale group="quiqqer/order" var="control.frontendUsers.orders.title"}</h2>
+    </div>
 
-<div class="quiqqer-order-profile-orders-list">
-    {foreach $orders as $Order}
-    {$this->renderOrder($Order)}
-    {foreachelse}
-    <p>{locale group="quiqqer/order" var="message.no.orders"}</p>
-    {/foreach}
-</div>
+    <div class="quiqqer-order-profile-orders-list" data-ref="order-list">
+        {foreach $orders as $Order}
+            {$this->renderOrder($Order)}
+            {foreachelse}
+            <p class="text-muted">{locale group="quiqqer/order" var="message.no.orders"}</p>
+        {/foreach}
+    </div>
 
-{if $sheetsMax && $sheetsMax != 1}
-<div class="quiqqer-order-profile-orders-pagination">
-    {control
-    control="QUI\Controls\Navigating\Pagination"
-    useAjax=true
-    Project=$Project
-    limit=$sheetLimit
-    sheets=$sheetsMax
-    sheet=$sheetCurrent
-    }
-</div>
-{/if}
\ No newline at end of file
+    {if $sheetsMax && $sheetsMax != 1}
+        <div class="quiqqer-order-profile-orders-pagination" data-ref="pagination">
+            {control
+            control="QUI\Controls\Navigating\Pagination"
+            useAjax=true
+            Project=$Project
+            limit=$sheetLimit
+            sheets=$sheetsMax
+            sheet=$sheetCurrent
+            }
+        </div>
+    {/if}
+
+</section>
\ No newline at end of file
diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
index 2135ea16..3b4efa85 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.php
@@ -216,6 +216,9 @@ class_exists('QUI\ERP\Shipping\ShippingStatus\Status')
      */
     public function renderArticle(QUI\ERP\Accounting\Article $Article): string
     {
+        $Settings = QUI\ERP\Order\Settings::getInstance();
+        $showImage = $Settings->get('userProfile', 'showArticleImage');
+        $noLink = $Settings->get('userProfile', 'disableProductLinks');
         $Engine = QUI::getTemplateManager()->getEngine();
         $Product = null;
         $Image = null;
@@ -244,6 +247,8 @@ public function renderArticle(QUI\ERP\Accounting\Article $Article): string
             'Article' => $Article,
             'Product' => $Product,
             'Image' => $Image,
+            'showImage' => $showImage,
+            'noLink' => $noLink,
             'Project' => QUI::getProjectManager()->get()
         ]);
 
-- 
GitLab


From 97b6e8ebd3fa0070b966bdacdd6689efc551607d Mon Sep 17 00:00:00 2001
From: Michael Danielczok <michael@pcsg.de>
Date: Mon, 24 Feb 2025 15:44:57 +0100
Subject: [PATCH 17/17] fix: adjust user profile order

---
 .../Controls/UserOrders.Order.html            |  4 ++-
 .../FrontendUsers/Controls/UserOrders.css     | 26 ++++++++++---------
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html
index 120f9eae..20b5c109 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.Order.html
@@ -89,7 +89,9 @@
         {if isset($orderStatus)}
             <div class="quiqqer-order-profile-orders-order__group quiqqer-order-profile-orders-order-footer-orderStatus">
                 <span class="quiqqer-order-profile-orders-order__label">{locale group="quiqqer/order" var="control.profile.orders.order.orderStatus"}:</span>
-                <div class="quiqqer-order-profile-orders-order__value">{$orderStatus}</div>
+                <div class="quiqqer-order-profile-orders-order__value">
+                    <span class="badge badge-primary">{$orderStatus}</span>
+                </div>
             </div>
         {/if}
     </footer>
diff --git a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css
index ad0c4a21..0da55d94 100644
--- a/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css
+++ b/src/QUI/ERP/Order/FrontendUsers/Controls/UserOrders.css
@@ -5,6 +5,7 @@
     --_box-bgColor: var(--box-bgColor, #f6f6f6);
     --_borderColor: var(--borderColor, #ddd);
     --_borderWidth: var(--borderWidth, 1px);
+    --_order-borderRadius: var(--order-borderRadius, 0.5rem);
     --_scrollMarginTop: var(--scrollMarginTop,var(--_qui-template-scrollMarginTop, 0px));
 }
 
@@ -19,6 +20,18 @@
     font-size: var(--_label-fontSize);
 }
 
+/** One Order
+ =============================================== */
+:where(.quiqqer-order-profile-orders-order) {
+    container-type: inline-size;
+    container-name: quiqqer-order-profile-orders-order;
+
+    overflow: hidden;
+    border-radius: var(--_order-borderRadius);
+    border: var(--_borderWidth) solid var(--_borderColor);
+    min-width: 0;
+}
+
 /* header */
 :where(.quiqqer-order-profile-orders-order__header) {
     background: var(--_box-bgColor);
@@ -32,17 +45,6 @@
     text-align: right;
 }
 
-/** One Order
- =============================================== */
-
-:where(.quiqqer-order-profile-orders-order) {
-    container-type: inline-size;
-    container-name: quiqqer-order-profile-orders-order;
-
-    border: var(--_borderWidth) solid var(--_borderColor);
-    min-width: 0;
-}
-
 /* article list */
 .quiqqer-order-profile-orders-order-articles {
     padding: var(--_box-padding);
@@ -61,7 +63,7 @@
     width: calc(10rem - 0.5rem);
     height: calc(10rem - 0.5rem);
     background: var(--_box-bgColor);
-    border-radius: 0.5rem;
+    border-radius: var(--_order-borderRadius);
     overflow: hidden;
     display: grid;
     place-content: center;
-- 
GitLab