index.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <?php
  2. require_once __DIR__ . '/../config.php';
  3. require_once __DIR__ . '/../includes/functions.php';
  4. require_once __DIR__ . '/../includes/backup.php';
  5. if (empty($_SESSION['admin_logged_in'])) {
  6. header('Location: login.php');
  7. exit;
  8. }
  9. $pageTitle = 'Admin Dashboard';
  10. $backupAutoMessage = '';
  11. $backupAutoMessageType = '';
  12. try {
  13. $backup = backupCreateAutomaticIfDue();
  14. if ($backup !== null) {
  15. $backupAutoMessage =
  16. 'Automatisches Backup wurde erstellt: ' .
  17. $backup['filename'] .
  18. '.';
  19. $backupAutoMessageType = 'success';
  20. }
  21. } catch (Throwable $exception) {
  22. $backupAutoMessage =
  23. 'Automatisches Backup konnte nicht erstellt werden: ' .
  24. $exception->getMessage();
  25. $backupAutoMessageType = 'warning';
  26. }
  27. $orders = getOrders();
  28. $backorderGroups = getBackorderGroups();
  29. $backorderCount = 0;
  30. foreach ($backorderGroups as $group) {
  31. $backorderCount += (int) $group['to_be_backordered'] + (int) $group['ordered'];
  32. }
  33. $stats = [
  34. 'open' => 0,
  35. 'partial' => 0,
  36. 'processed' => 0,
  37. 'cancelled' => 0,
  38. 'backorder' => $backorderCount,
  39. ];
  40. foreach ($orders as $order) {
  41. if ($order['status'] === 'cancelled') {
  42. $stats['cancelled']++;
  43. } elseif ($order['status'] === 'processed') {
  44. $stats['processed']++;
  45. } elseif ($order['status'] === 'partial') {
  46. $stats['partial']++;
  47. } else {
  48. $stats['open']++;
  49. }
  50. }
  51. $recentOrders = array_values(array_filter($orders, function ($order) {
  52. $label = getOrderStatusLabel($order);
  53. if ($label !== 'Offen' && $label !== 'Teilweise bearbeitet') {
  54. return false;
  55. }
  56. foreach ($order['items'] as $item) {
  57. if (!empty($item['is_processed'])) {
  58. continue;
  59. }
  60. if (trim((string) ($item['backorder_status'] ?? '')) === '') {
  61. return true;
  62. }
  63. }
  64. return false;
  65. }));
  66. usort($recentOrders, function ($left, $right) {
  67. return strcmp($right['created_at'], $left['created_at']);
  68. });
  69. $recentOrders = array_slice($recentOrders, 0, 5);
  70. $outstandingItems = [];
  71. foreach ($orders as $order) {
  72. $label = getOrderStatusLabel($order);
  73. if ($label !== 'Offen' && $label !== 'Teilweise bearbeitet') {
  74. continue;
  75. }
  76. foreach ($order['items'] as $item) {
  77. if (!empty($item['is_processed'])) {
  78. continue;
  79. }
  80. if (trim((string) ($item['backorder_status'] ?? '')) !== '') {
  81. continue;
  82. }
  83. $outstandingItems[] = [
  84. 'order_id' => $order['id'],
  85. 'customer_name' => $order['customer_name'],
  86. 'organization_label' => $order['organization_label'],
  87. 'created_at' => $order['created_at'],
  88. 'product_name' => $item['product_name'],
  89. 'size' => $item['size'],
  90. 'availability_label' => $item['availability_label'],
  91. ];
  92. }
  93. }
  94. usort($outstandingItems, function ($left, $right) {
  95. $cmp = strcmp($left['created_at'], $right['created_at']);
  96. if ($cmp !== 0) {
  97. return $cmp;
  98. }
  99. $cmp = strcmp($left['order_id'], $right['order_id']);
  100. if ($cmp !== 0) {
  101. return $cmp;
  102. }
  103. return strcmp($left['product_name'], $right['product_name']);
  104. });
  105. $bodyClass = 'admin-page';
  106. include __DIR__ . '/../includes/header.php';
  107. ?>
  108. <div class="admin-header">
  109. <h2>Admin Dashboard</h2>
  110. <div class="admin-dashboard-actions">
  111. <a href="orders.php" class="btn">Bestellungen</a>
  112. <details class="admin-actions-dropdown">
  113. <summary class="btn btn-secondary">Verwaltung</summary>
  114. <div class="admin-actions-menu">
  115. <a href="products.php">Produkte verwalten</a>
  116. <a href="categories.php">Kategorien verwalten</a>
  117. <a href="organizations.php">Organisationen verwalten</a>
  118. <a href="settings.php">Einstellungen</a>
  119. <a href="faq.php">FAQ bearbeiten</a>
  120. <a href="backorders.php">Nachbestellungen verwalten</a>
  121. <a href="admins.php">Admins verwalten</a>
  122. <form method="POST" action="login.php" class="inline-form">
  123. <?php echo csrfField(); ?>
  124. <button type="submit" name="logout" class="btn btn-secondary btn-small">Abmelden</button>
  125. </form>
  126. </div>
  127. </details>
  128. </div>
  129. </div>
  130. <?php if ($backupAutoMessage !== ''): ?>
  131. <div class="alert alert-<?php echo escape($backupAutoMessageType); ?>">
  132. <?php echo escape($backupAutoMessage); ?>
  133. </div>
  134. <?php endif; ?>
  135. <div class="admin-stats">
  136. <div class="stat-card">
  137. <h3>Offen</h3>
  138. <div class="stat-value"><?php echo $stats['open']; ?></div>
  139. </div>
  140. <div class="stat-card">
  141. <h3>Teilweise bearbeitet</h3>
  142. <div class="stat-value"><?php echo $stats['partial']; ?></div>
  143. </div>
  144. <div class="stat-card">
  145. <h3>Bearbeitet</h3>
  146. <div class="stat-value"><?php echo $stats['processed']; ?></div>
  147. </div>
  148. <div class="stat-card">
  149. <h3>Storniert</h3>
  150. <div class="stat-value"><?php echo $stats['cancelled']; ?></div>
  151. </div>
  152. <div class="stat-card">
  153. <h3>Nachbestellung</h3>
  154. <div class="stat-value"><?php echo $stats['backorder']; ?></div>
  155. </div>
  156. </div>
  157. <h3 class="section-title mt-4">Bestellungen mit Aktion erforderlich</h3>
  158. <?php if (empty($recentOrders)): ?>
  159. <p>Keine Bestellungen mit erforderlicher Aktion.</p>
  160. <?php else: ?>
  161. <div class="table-responsive">
  162. <table class="responsive-table">
  163. <thead>
  164. <tr>
  165. <th>Bestellnummer</th>
  166. <th>Name</th>
  167. <th>Organisation</th>
  168. <th>Erstellt</th>
  169. <th>Status</th>
  170. <th>Nachbestellung</th>
  171. <th>Aktionen</th>
  172. </tr>
  173. </thead>
  174. <tbody>
  175. <?php foreach ($recentOrders as $order):
  176. $backorderSummary = getOrderOpenBackorderSummary($order);
  177. ?>
  178. <tr>
  179. <td data-label="Bestellnummer"><strong><?php echo escape($order['id']); ?></strong></td>
  180. <td data-label="Name"><?php echo escape($order['customer_name']); ?></td>
  181. <td data-label="Organisation"><?php echo escape($order['organization_label']); ?></td>
  182. <td data-label="Erstellt"><?php echo escape(formatDate($order['created_at'])); ?></td>
  183. <td data-label="Status"><span class="status <?php echo escape(getOrderStatusClass($order)); ?>"><?php echo escape(getOrderStatusLabel($order)); ?></span></td>
  184. <td data-label="Nachbestellung">
  185. <?php if ($backorderSummary['label'] !== ''): ?>
  186. <span class="status <?php echo escape($backorderSummary['class']); ?>"><?php echo escape($backorderSummary['label']); ?></span>
  187. <?php else: ?>
  188. -
  189. <?php endif; ?>
  190. </td>
  191. <td data-label="Aktionen"><a href="order.php?id=<?php echo urlencode($order['id']); ?>" class="btn btn-small">Details</a></td>
  192. </tr>
  193. <?php endforeach; ?>
  194. </tbody>
  195. </table>
  196. </div>
  197. <?php endif; ?>
  198. <h3 class="section-title mt-4">Offene Positionen</h3>
  199. <?php if (empty($outstandingItems)): ?>
  200. <p>Keine offenen Positionen vorhanden.</p>
  201. <?php else: ?>
  202. <div class="table-responsive">
  203. <table class="responsive-table">
  204. <thead>
  205. <tr>
  206. <th>Bestellnummer</th>
  207. <th>Name</th>
  208. <th>Organisation</th>
  209. <th>Artikel</th>
  210. <th>Größe</th>
  211. <th>Lieferhinweis</th>
  212. <th>Erstellt</th>
  213. <th>Aktionen</th>
  214. </tr>
  215. </thead>
  216. <tbody>
  217. <?php foreach ($outstandingItems as $row): ?>
  218. <tr>
  219. <td data-label="Bestellnummer"><strong><?php echo escape($row['order_id']); ?></strong></td>
  220. <td data-label="Name"><?php echo escape($row['customer_name']); ?></td>
  221. <td data-label="Organisation"><?php echo escape($row['organization_label']); ?></td>
  222. <td data-label="Artikel"><?php echo escape($row['product_name']); ?></td>
  223. <td data-label="Größe"><?php echo $row['size'] !== '' ? escape($row['size']) : '-'; ?></td>
  224. <td data-label="Lieferhinweis"><?php echo $row['availability_label'] !== '' ? escape($row['availability_label']) : '-'; ?></td>
  225. <td data-label="Erstellt"><?php echo escape(formatDate($row['created_at'])); ?></td>
  226. <td data-label="Aktionen"><a href="order.php?id=<?php echo urlencode($row['order_id']); ?>" class="btn btn-small">Details</a></td>
  227. </tr>
  228. <?php endforeach; ?>
  229. </tbody>
  230. </table>
  231. </div>
  232. <?php endif; ?>
  233. <?php include __DIR__ . '/../includes/footer.php'; ?>