orders.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. require_once __DIR__ . '/../config.php';
  3. require_once __DIR__ . '/../includes/functions.php';
  4. if (empty($_SESSION['admin_logged_in'])) {
  5. header('Location: login.php');
  6. exit;
  7. }
  8. expirePendingOrders();
  9. $pageTitle = 'Bestellungen';
  10. $message = '';
  11. $messageType = '';
  12. if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['toggle_item_processed'])) {
  13. $result = toggleOrderItemProcessed($_POST['order_id'] ?? '', (int) ($_POST['item_index'] ?? -1));
  14. $message = $result['success'] ? 'Position wurde aktualisiert.' : $result['message'];
  15. $messageType = $result['success'] ? 'success' : 'error';
  16. }
  17. if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['cancel_order'])) {
  18. $adminUsername = $_SESSION['admin_username'] ?? '';
  19. $result = cancelOrder($_POST['order_id'] ?? '', $adminUsername, $_POST['cancellation_reason'] ?? '');
  20. $message = $result['success'] ? 'Bestellung wurde storniert.' : $result['message'];
  21. $messageType = $result['success'] ? 'success' : 'error';
  22. }
  23. $orders = getOrders();
  24. usort($orders, function ($left, $right) {
  25. return strcmp($right['created_at'], $left['created_at']);
  26. });
  27. $filter = trim((string) ($_GET['filter'] ?? 'all'));
  28. $searchOrderId = trim((string) ($_GET['order_id'] ?? ''));
  29. $selectedOrderId = trim((string) ($_GET['details'] ?? $searchOrderId));
  30. if ($searchOrderId !== '') {
  31. $orders = array_values(array_filter($orders, function ($order) use ($searchOrderId) {
  32. return stripos($order['id'], $searchOrderId) !== false;
  33. }));
  34. }
  35. if ($filter !== 'all') {
  36. $orders = array_values(array_filter($orders, function ($order) use ($filter) {
  37. switch ($filter) {
  38. case 'unconfirmed':
  39. return $order['confirmation_status'] === 'pending';
  40. case 'expired':
  41. return $order['confirmation_status'] === 'expired';
  42. case 'open':
  43. return $order['confirmation_status'] !== 'pending' && $order['status'] === 'open';
  44. case 'partial':
  45. return $order['status'] === 'partial';
  46. case 'processed':
  47. return $order['status'] === 'processed';
  48. case 'cancelled':
  49. return $order['status'] === 'cancelled';
  50. }
  51. return true;
  52. }));
  53. }
  54. $selectedOrder = $selectedOrderId !== '' ? getOrderById($selectedOrderId) : null;
  55. $bodyClass = 'admin-page';
  56. include __DIR__ . '/../includes/header.php';
  57. ?>
  58. <div class="admin-header">
  59. <h2>Bestellungen</h2>
  60. <div>
  61. <a href="index.php" class="btn btn-secondary">Zurück zum Dashboard</a>
  62. </div>
  63. </div>
  64. <?php if ($message !== ''): ?>
  65. <div class="alert alert-<?php echo escape($messageType); ?>">
  66. <?php echo escape($message); ?>
  67. </div>
  68. <?php endif; ?>
  69. <div class="panel">
  70. <form method="GET" class="admin-filter-form">
  71. <div class="admin-filter-field admin-filter-field-wide">
  72. <label for="order_id">Bestellnummer suchen</label>
  73. <input type="text" id="order_id" name="order_id" value="<?php echo escape($searchOrderId); ?>" placeholder="z. B. FWFS-2026-001">
  74. </div>
  75. <div>
  76. <label for="filter">Filter</label>
  77. <select id="filter" name="filter">
  78. <option value="all" <?php echo $filter === 'all' ? 'selected' : ''; ?>>Alle</option>
  79. <option value="unconfirmed" <?php echo $filter === 'unconfirmed' ? 'selected' : ''; ?>>Unbestätigt</option>
  80. <option value="expired" <?php echo $filter === 'expired' ? 'selected' : ''; ?>>Bestätigung abgelaufen</option>
  81. <option value="open" <?php echo $filter === 'open' ? 'selected' : ''; ?>>Offen</option>
  82. <option value="partial" <?php echo $filter === 'partial' ? 'selected' : ''; ?>>Teilweise bearbeitet</option>
  83. <option value="processed" <?php echo $filter === 'processed' ? 'selected' : ''; ?>>Bearbeitet</option>
  84. <option value="cancelled" <?php echo $filter === 'cancelled' ? 'selected' : ''; ?>>Storniert</option>
  85. </select>
  86. </div>
  87. <div class="admin-filter-actions">
  88. <button type="submit" class="btn">Filtern</button>
  89. <a href="orders.php" class="btn btn-secondary">Zurücksetzen</a>
  90. </div>
  91. </form>
  92. </div>
  93. <?php if (empty($orders)): ?>
  94. <div class="alert alert-info">
  95. <p>Keine Bestellungen gefunden.</p>
  96. </div>
  97. <?php else: ?>
  98. <div class="table-responsive">
  99. <table class="responsive-table">
  100. <thead>
  101. <tr>
  102. <th>Bestellnummer</th>
  103. <th>Name</th>
  104. <th>Organisation</th>
  105. <th>Artikel</th>
  106. <th>Erstellt</th>
  107. <th>Status</th>
  108. <th>Aktionen</th>
  109. </tr>
  110. </thead>
  111. <tbody>
  112. <?php foreach ($orders as $order): ?>
  113. <tr>
  114. <td data-label="Bestellnummer"><strong><?php echo escape($order['id']); ?></strong></td>
  115. <td data-label="Name"><?php echo escape($order['customer_name']); ?></td>
  116. <td data-label="Organisation"><?php echo escape($order['organization_label']); ?></td>
  117. <td data-label="Artikel"><?php echo count($order['items']); ?></td>
  118. <td data-label="Erstellt"><?php echo escape(formatDate($order['created_at'])); ?></td>
  119. <td data-label="Status"><span class="status <?php echo escape(getOrderStatusClass($order)); ?>"><?php echo escape(getOrderStatusLabel($order)); ?></span></td>
  120. <td data-label="Aktionen">
  121. <a href="orders.php?details=<?php echo urlencode($order['id']); ?>" class="btn btn-small">Details</a>
  122. </td>
  123. </tr>
  124. <?php endforeach; ?>
  125. </tbody>
  126. </table>
  127. </div>
  128. <?php endif; ?>
  129. <?php if ($selectedOrder !== null): ?>
  130. <div class="panel">
  131. <h3>Bestellung <?php echo escape($selectedOrder['id']); ?></h3>
  132. <p><strong>Status:</strong> <span class="status <?php echo escape(getOrderStatusClass($selectedOrder)); ?>"><?php echo escape(getOrderStatusLabel($selectedOrder)); ?></span></p>
  133. <p><strong>Name:</strong> <?php echo escape($selectedOrder['customer_name']); ?></p>
  134. <p><strong>E-Mail:</strong> <?php echo escape($selectedOrder['customer_email']); ?></p>
  135. <p><strong>Organisation:</strong> <?php echo escape($selectedOrder['organization_label']); ?></p>
  136. <p><strong>Erstellt:</strong> <?php echo escape(formatDate($selectedOrder['created_at'])); ?></p>
  137. <?php if ($selectedOrder['confirmed_at'] !== ''): ?>
  138. <p><strong>Bestätigt:</strong> <?php echo escape(formatDate($selectedOrder['confirmed_at'])); ?></p>
  139. <?php endif; ?>
  140. <?php if ($selectedOrder['confirmation_status'] === 'pending'): ?>
  141. <p><strong>Bestätigung offen bis:</strong> <?php echo escape(formatDate($selectedOrder['confirmation_expires_at'])); ?></p>
  142. <?php endif; ?>
  143. <?php if ($selectedOrder['admin_notified_at'] !== ''): ?>
  144. <p><strong>Intern weitergeleitet:</strong> <?php echo escape(formatDate($selectedOrder['admin_notified_at'])); ?></p>
  145. <?php endif; ?>
  146. <p><strong>Kommentar:</strong><br><?php echo $selectedOrder['comment'] !== '' ? nl2br(escape($selectedOrder['comment'])) : 'Kein Kommentar'; ?></p>
  147. <?php if ($selectedOrder['status'] === 'cancelled'): ?>
  148. <div class="alert alert-warning">
  149. <p><strong>Storniert am:</strong> <?php echo escape(formatDate($selectedOrder['cancelled_at'])); ?></p>
  150. <p><strong>Storniert durch:</strong> <?php echo escape($selectedOrder['cancelled_by']); ?></p>
  151. <p><strong>Stornogrund:</strong><br><?php echo $selectedOrder['cancellation_reason'] !== '' ? nl2br(escape($selectedOrder['cancellation_reason'])) : 'Kein Grund angegeben'; ?></p>
  152. </div>
  153. <?php endif; ?>
  154. <h4>Positionen</h4>
  155. <div class="table-responsive">
  156. <table class="responsive-table table-compact">
  157. <thead>
  158. <tr>
  159. <th>Artikel</th>
  160. <th>Größe</th>
  161. <th>Lieferhinweis</th>
  162. <th>Bearbeitet</th>
  163. <th>Aktion</th>
  164. </tr>
  165. </thead>
  166. <tbody>
  167. <?php foreach ($selectedOrder['items'] as $index => $item): ?>
  168. <tr>
  169. <td data-label="Artikel"><?php echo escape($item['product_name']); ?></td>
  170. <td data-label="Größe"><?php echo $item['size'] !== '' ? escape($item['size']) : '-'; ?></td>
  171. <td data-label="Lieferhinweis"><?php echo $item['availability_label'] !== '' ? escape($item['availability_label']) : '-'; ?></td>
  172. <td data-label="Bearbeitet">
  173. <span class="status <?php echo !empty($item['is_processed']) ? 'status-processed' : 'status-open'; ?>">
  174. <?php echo !empty($item['is_processed']) ? 'Ja' : 'Nein'; ?>
  175. </span>
  176. </td>
  177. <td data-label="Aktion">
  178. <?php if ($selectedOrder['status'] !== 'cancelled' && $selectedOrder['confirmation_status'] !== 'pending' && $selectedOrder['confirmation_status'] !== 'expired'): ?>
  179. <form method="POST">
  180. <input type="hidden" name="order_id" value="<?php echo escape($selectedOrder['id']); ?>">
  181. <input type="hidden" name="item_index" value="<?php echo (int) $index; ?>">
  182. <button type="submit" name="toggle_item_processed" class="btn btn-small">
  183. <?php echo !empty($item['is_processed']) ? 'Als offen markieren' : 'Als bearbeitet markieren'; ?>
  184. </button>
  185. </form>
  186. <?php else: ?>
  187. -
  188. <?php endif; ?>
  189. </td>
  190. </tr>
  191. <?php endforeach; ?>
  192. </tbody>
  193. </table>
  194. </div>
  195. <?php if ($selectedOrder['status'] !== 'cancelled'): ?>
  196. <h4>Bestellung stornieren</h4>
  197. <form method="POST" onsubmit="return confirm('Bestellung wirklich stornieren?');">
  198. <input type="hidden" name="order_id" value="<?php echo escape($selectedOrder['id']); ?>">
  199. <div class="form-group">
  200. <label for="cancellation_reason">Stornogrund</label>
  201. <textarea id="cancellation_reason" name="cancellation_reason" rows="3" placeholder="Optionaler Grund"></textarea>
  202. </div>
  203. <button type="submit" name="cancel_order" class="btn">Bestellung stornieren</button>
  204. </form>
  205. <?php endif; ?>
  206. </div>
  207. <?php endif; ?>
  208. <?php include __DIR__ . '/../includes/footer.php'; ?>