From dd4c46768f4534c182ee8f197d2c3277e5289ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Gla=CC=88ser?= Date: Tue, 16 Jun 2026 15:08:56 +0200 Subject: [PATCH] Add OTC order date picker --- modules/erp/bestellungen/service.php | 4 +-- modules/erp/direktverkauf/api/otc-order.php | 10 ++++++- modules/shared/auth/ui/home.php | 29 ++++++++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/modules/erp/bestellungen/service.php b/modules/erp/bestellungen/service.php index 986e089..ee55ce6 100644 --- a/modules/erp/bestellungen/service.php +++ b/modules/erp/bestellungen/service.php @@ -127,10 +127,10 @@ function create_direct_sales_order(PDO $pdo, array $fields): array { $stmt = $pdo->prepare( "INSERT INTO sales_order ( - external_ref, party_id, order_source, order_status, payment_status, payment_method_id, + external_ref, party_id, order_source, order_date, order_status, payment_status, payment_method_id, amount_net, amount_shipping, amount_tax, amount_discount, total_amount, currency, imported_at, created_at, updated_at ) VALUES ( - '', :party_id, 'direct', 'imported', 'paid', :payment_method_id, + '', :party_id, 'direct', :order_date, 'imported', 'paid', :payment_method_id, :amount_net, 0, 0, 0, :total_amount, 'CHF', NOW(), NOW(), NOW() ) RETURNING id, external_ref" diff --git a/modules/erp/direktverkauf/api/otc-order.php b/modules/erp/direktverkauf/api/otc-order.php index 02d308c..3276ebe 100644 --- a/modules/erp/direktverkauf/api/otc-order.php +++ b/modules/erp/direktverkauf/api/otc-order.php @@ -30,7 +30,7 @@ if (!is_array($data)) { json_response(400, ['ok' => false, 'error' => 'JSON object expected']); } -$required = ['products', 'totalPrice', 'paymentMethod', 'billing']; +$required = ['products', 'totalPrice', 'orderDate', 'paymentMethod', 'billing']; foreach ($required as $field) { if (!array_key_exists($field, $data)) { json_response(422, ['ok' => false, 'error' => "Missing field: {$field}"]); @@ -39,6 +39,7 @@ foreach ($required as $field) { $products = $data['products']; $totalPrice = parse_number($data['totalPrice']); +$orderDate = trim((string) $data['orderDate']); $paymentMethodCode = trim((string) $data['paymentMethod']); $billing = is_array($data['billing']) ? $data['billing'] : []; @@ -50,6 +51,12 @@ if ($totalPrice === null || $totalPrice <= 0) { json_response(422, ['ok' => false, 'error' => 'Invalid total price']); } +$orderDateTime = DateTimeImmutable::createFromFormat('!Y-m-d', $orderDate); +$orderDateErrors = DateTimeImmutable::getLastErrors(); +if ($orderDateTime === false || $orderDateErrors === false || $orderDateErrors['warning_count'] > 0 || $orderDateErrors['error_count'] > 0) { + json_response(422, ['ok' => false, 'error' => 'Invalid order date']); +} + $resolvedProducts = []; $totalQty = 0.0; foreach ($products as $product) { @@ -94,6 +101,7 @@ try { ':payment_method_id' => $paymentMethodId, ':amount_net' => $totalPrice, ':total_amount' => $totalPrice, + ':order_date' => $orderDateTime->format('Y-m-d H:i:s'), ]); $orderId = (int) $order['id']; diff --git a/modules/shared/auth/ui/home.php b/modules/shared/auth/ui/home.php index 9dd6066..124d9ff 100644 --- a/modules/shared/auth/ui/home.php +++ b/modules/shared/auth/ui/home.php @@ -328,6 +328,13 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo '

Der Preis wird durch die Anzahl aller Flaschen geteilt und das Ergebnis ist der Preis jeder einzelnen Flasche.

'; echo ''; echo ''; + echo '
'; + echo '

Datum

'; + echo '
'; + echo ''; + echo ''; + echo '
'; + echo '
'; echo '
'; echo '

Bezahlung

'; echo '
'; @@ -713,6 +720,8 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo " const form = overlay.querySelector('[data-otc-order-form]');"; echo " const productInputs = Array.from(form.querySelectorAll('[data-otc-order-product]'));"; echo " const totalPriceInput = form.querySelector('[data-otc-order-total-price]');"; + echo " const orderDateInput = form.querySelector('[data-otc-order-date]');"; + echo " const orderDateDefaultValue = orderDateInput ? orderDateInput.value : '';"; echo " const paymentMethodInput = form.querySelector('[data-otc-order-payment-method]');"; echo " const firstNameInput = form.querySelector('[data-otc-order-first-name]');"; echo " const lastNameInput = form.querySelector('[data-otc-order-last-name]');"; @@ -734,6 +743,19 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo " const clearSuccess = () => {"; echo " if (successEl) { successEl.textContent = successDefaultText; successEl.classList.add('hidden'); }"; echo " };"; + echo " const getTodayValue = () => {"; + echo " const now = new Date();"; + echo " const year = now.getFullYear();"; + echo " const month = String(now.getMonth() + 1).padStart(2, '0');"; + echo " const day = String(now.getDate()).padStart(2, '0');"; + echo " return year + '-' + month + '-' + day;"; + echo " };"; + echo " const ensureCurrentOrderDate = () => {"; + echo " if (!orderDateInput) { return; }"; + echo " if (!orderDateInput.value || orderDateInput.value === orderDateDefaultValue) {"; + echo " orderDateInput.value = getTodayValue();"; + echo " }"; + echo " };"; echo " const toggleOverlay = (isOpen) => {"; echo " overlay.dataset.open = String(isOpen);"; echo " overlay.setAttribute('aria-hidden', String(!isOpen));"; @@ -742,6 +764,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo " if (isOpen) {"; echo " clearError();"; echo " clearSuccess();"; + echo " ensureCurrentOrderDate();"; echo " requestAnimationFrame(() => {"; echo " (productInputs[0] || totalPriceInput || submitBtn)?.focus();"; echo " });"; @@ -761,6 +784,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo " });"; echo " const isValid = totalQty > 0"; echo " && totalPrice > 0"; + echo " && !!getFieldValue(orderDateInput)"; echo " && !!getFieldValue(paymentMethodInput)"; echo " && !!getFieldValue(firstNameInput)"; echo " && !!getFieldValue(lastNameInput)"; @@ -776,6 +800,8 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo " errorMsg = 'Mindestens ein Produkt mit Menge > 0 erforderlich.';"; echo " } else if (totalPrice <= 0) {"; echo " errorMsg = 'Preis muss größer als 0 sein.';"; + echo " } else if (!getFieldValue(orderDateInput)) {"; + echo " errorMsg = 'Bestelldatum auswählen.';"; echo " } else if (!getFieldValue(paymentMethodInput)) {"; echo " errorMsg = 'Zahlungsart auswählen.';"; echo " } else if (!getFieldValue(firstNameInput) || !getFieldValue(lastNameInput) || !getFieldValue(streetInput) || !getFieldValue(houseNumberInput) || !getFieldValue(zipInput) || !getFieldValue(cityInput)) {"; @@ -819,7 +845,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo " toggleOverlay(false);"; echo " }"; echo " });"; - echo " [totalPriceInput, paymentMethodInput, firstNameInput, lastNameInput, streetInput, houseNumberInput, zipInput, cityInput].forEach((input) => {"; + echo " [totalPriceInput, orderDateInput, paymentMethodInput, firstNameInput, lastNameInput, streetInput, houseNumberInput, zipInput, cityInput].forEach((input) => {"; echo " if (!input) { return; }"; echo " input.addEventListener('input', updateFormState);"; echo " input.addEventListener('change', updateFormState);"; @@ -838,6 +864,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best echo " const orderData = {"; echo " products: products,"; echo " totalPrice: parseFloat(totalPriceInput.value || '0') || 0,"; + echo " orderDate: orderDateInput ? orderDateInput.value : '',"; echo " paymentMethod: paymentMethodInput ? paymentMethodInput.value : '',"; echo " billing: {"; echo " firstName: getFieldValue(firstNameInput),";