Add OTC order date picker

This commit is contained in:
2026-06-16 15:08:56 +02:00
parent 3dd5f5f1b4
commit dd4c46768f
3 changed files with 39 additions and 4 deletions
+2 -2
View File
@@ -127,10 +127,10 @@ function create_direct_sales_order(PDO $pdo, array $fields): array
{ {
$stmt = $pdo->prepare( $stmt = $pdo->prepare(
"INSERT INTO sales_order ( "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 amount_net, amount_shipping, amount_tax, amount_discount, total_amount, currency, imported_at, created_at, updated_at
) VALUES ( ) 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() :amount_net, 0, 0, 0, :total_amount, 'CHF', NOW(), NOW(), NOW()
) )
RETURNING id, external_ref" RETURNING id, external_ref"
+9 -1
View File
@@ -30,7 +30,7 @@ if (!is_array($data)) {
json_response(400, ['ok' => false, 'error' => 'JSON object expected']); json_response(400, ['ok' => false, 'error' => 'JSON object expected']);
} }
$required = ['products', 'totalPrice', 'paymentMethod', 'billing']; $required = ['products', 'totalPrice', 'orderDate', 'paymentMethod', 'billing'];
foreach ($required as $field) { foreach ($required as $field) {
if (!array_key_exists($field, $data)) { if (!array_key_exists($field, $data)) {
json_response(422, ['ok' => false, 'error' => "Missing field: {$field}"]); json_response(422, ['ok' => false, 'error' => "Missing field: {$field}"]);
@@ -39,6 +39,7 @@ foreach ($required as $field) {
$products = $data['products']; $products = $data['products'];
$totalPrice = parse_number($data['totalPrice']); $totalPrice = parse_number($data['totalPrice']);
$orderDate = trim((string) $data['orderDate']);
$paymentMethodCode = trim((string) $data['paymentMethod']); $paymentMethodCode = trim((string) $data['paymentMethod']);
$billing = is_array($data['billing']) ? $data['billing'] : []; $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']); 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 = []; $resolvedProducts = [];
$totalQty = 0.0; $totalQty = 0.0;
foreach ($products as $product) { foreach ($products as $product) {
@@ -94,6 +101,7 @@ try {
':payment_method_id' => $paymentMethodId, ':payment_method_id' => $paymentMethodId,
':amount_net' => $totalPrice, ':amount_net' => $totalPrice,
':total_amount' => $totalPrice, ':total_amount' => $totalPrice,
':order_date' => $orderDateTime->format('Y-m-d H:i:s'),
]); ]);
$orderId = (int) $order['id']; $orderId = (int) $order['id'];
+28 -1
View File
@@ -328,6 +328,13 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo '<p class="sg-body sg-form-sections-card__sentence">Der Preis wird durch die Anzahl aller Flaschen geteilt und das Ergebnis ist der Preis jeder einzelnen Flasche.</p>'; echo '<p class="sg-body sg-form-sections-card__sentence">Der Preis wird durch die Anzahl aller Flaschen geteilt und das Ergebnis ist der Preis jeder einzelnen Flasche.</p>';
echo '</div>'; echo '</div>';
echo '</section>'; echo '</section>';
echo '<section class="sg-form-sections-card__chapter" aria-labelledby="otc-order-date-title">';
echo '<h2 id="otc-order-date-title" class="sg-strong sg-form-sections-card__chapter-title">Datum</h2>';
echo '<div class="sg-form-sections-card__field-group">';
echo '<label class="sg-label" for="otc-order-date">Bestelldatum</label>';
echo '<input class="sg-interaction-element sg-input-single-line" type="date" id="otc-order-date" value="' . htmlspecialchars(date('Y-m-d'), ENT_QUOTES, 'UTF-8') . '" data-otc-order-date>';
echo '</div>';
echo '</section>';
echo '<section class="sg-form-sections-card__chapter" aria-labelledby="otc-payment-title">'; echo '<section class="sg-form-sections-card__chapter" aria-labelledby="otc-payment-title">';
echo '<h2 id="otc-payment-title" class="sg-strong sg-form-sections-card__chapter-title">Bezahlung</h2>'; echo '<h2 id="otc-payment-title" class="sg-strong sg-form-sections-card__chapter-title">Bezahlung</h2>';
echo '<div class="sg-form-sections-card__field-group">'; echo '<div class="sg-form-sections-card__field-group">';
@@ -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 form = overlay.querySelector('[data-otc-order-form]');";
echo " const productInputs = Array.from(form.querySelectorAll('[data-otc-order-product]'));"; echo " const productInputs = Array.from(form.querySelectorAll('[data-otc-order-product]'));";
echo " const totalPriceInput = form.querySelector('[data-otc-order-total-price]');"; 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 paymentMethodInput = form.querySelector('[data-otc-order-payment-method]');";
echo " const firstNameInput = form.querySelector('[data-otc-order-first-name]');"; echo " const firstNameInput = form.querySelector('[data-otc-order-first-name]');";
echo " const lastNameInput = form.querySelector('[data-otc-order-last-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 " const clearSuccess = () => {";
echo " if (successEl) { successEl.textContent = successDefaultText; successEl.classList.add('hidden'); }"; echo " if (successEl) { successEl.textContent = successDefaultText; successEl.classList.add('hidden'); }";
echo " };"; 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 " const toggleOverlay = (isOpen) => {";
echo " overlay.dataset.open = String(isOpen);"; echo " overlay.dataset.open = String(isOpen);";
echo " overlay.setAttribute('aria-hidden', 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 " if (isOpen) {";
echo " clearError();"; echo " clearError();";
echo " clearSuccess();"; echo " clearSuccess();";
echo " ensureCurrentOrderDate();";
echo " requestAnimationFrame(() => {"; echo " requestAnimationFrame(() => {";
echo " (productInputs[0] || totalPriceInput || submitBtn)?.focus();"; echo " (productInputs[0] || totalPriceInput || submitBtn)?.focus();";
echo " });"; echo " });";
@@ -761,6 +784,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $best
echo " });"; echo " });";
echo " const isValid = totalQty > 0"; echo " const isValid = totalQty > 0";
echo " && totalPrice > 0"; echo " && totalPrice > 0";
echo " && !!getFieldValue(orderDateInput)";
echo " && !!getFieldValue(paymentMethodInput)"; echo " && !!getFieldValue(paymentMethodInput)";
echo " && !!getFieldValue(firstNameInput)"; echo " && !!getFieldValue(firstNameInput)";
echo " && !!getFieldValue(lastNameInput)"; 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 " errorMsg = 'Mindestens ein Produkt mit Menge > 0 erforderlich.';";
echo " } else if (totalPrice <= 0) {"; echo " } else if (totalPrice <= 0) {";
echo " errorMsg = 'Preis muss größer als 0 sein.';"; 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 " } else if (!getFieldValue(paymentMethodInput)) {";
echo " errorMsg = 'Zahlungsart auswählen.';"; echo " errorMsg = 'Zahlungsart auswählen.';";
echo " } else if (!getFieldValue(firstNameInput) || !getFieldValue(lastNameInput) || !getFieldValue(streetInput) || !getFieldValue(houseNumberInput) || !getFieldValue(zipInput) || !getFieldValue(cityInput)) {"; 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 " toggleOverlay(false);";
echo " }"; echo " }";
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 " if (!input) { return; }";
echo " input.addEventListener('input', updateFormState);"; echo " input.addEventListener('input', updateFormState);";
echo " input.addEventListener('change', 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 " const orderData = {";
echo " products: products,"; echo " products: products,";
echo " totalPrice: parseFloat(totalPriceInput.value || '0') || 0,"; echo " totalPrice: parseFloat(totalPriceInput.value || '0') || 0,";
echo " orderDate: orderDateInput ? orderDateInput.value : '',";
echo " paymentMethod: paymentMethodInput ? paymentMethodInput.value : '',"; echo " paymentMethod: paymentMethodInput ? paymentMethodInput.value : '',";
echo " billing: {"; echo " billing: {";
echo " firstName: getFieldValue(firstNameInput),"; echo " firstName: getFieldValue(firstNameInput),";