Browse code

Integrate slot checker service and use to validate time slots conflicts

Benjamin Roth authored on25/07/2024 10:49:45
Showing4 changed files
... ...
@@ -18,3 +18,9 @@ services:
18 18
         arguments:
19 19
             - "@database_connection"
20 20
             - "@logger"
21
+
22
+    vonrotenberg.wa.slot_checker:
23
+        class: vonRotenberg\WeinanlieferungBundle\SlotChecker
24
+        public: true
25
+        arguments:
26
+            - "@database_connection"
... ...
@@ -41,3 +41,7 @@ $GLOBALS['TL_LANG']['tl_vr_wa_slot']['info_legend'] = 'Zusätzliche Informatione
41 41
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['booking_legend'] = 'Buchbarkeits-Einstellungen';
42 42
 
43 43
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['back'] = 'Zurück';
44
+
45
+
46
+$GLOBALS['TL_LANG']['ERR']['wa_slot_nodate'] = 'Sie müssen ein gültiges Datum angeben';
47
+$GLOBALS['TL_LANG']['ERR']['wa_slot_conflict'] = 'Es besteht ein Konflikt mit einem bereits bestehenden Zeitslot';
... ...
@@ -15,11 +15,14 @@ namespace vonRotenberg\WeinanlieferungBundle\EventListener\DataContainer;
15 15
 use Contao\CoreBundle\ServiceAnnotation\Callback;
16 16
 use Contao\DataContainer;
17 17
 use Contao\Date;
18
+use Contao\Input;
18 19
 use Contao\StringUtil;
20
+use Contao\System;
19 21
 use Doctrine\DBAL\Connection;
20 22
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel;
21 23
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
22 24
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel;
25
+use vonRotenberg\WeinanlieferungBundle\SlotChecker;
23 26
 
24 27
 class WeinanlieferungSlotContainerListener
25 28
 {
... ...
@@ -65,18 +68,27 @@ class WeinanlieferungSlotContainerListener
65 68
     }
66 69
 
67 70
     /**
68
-     * @Callback(table="tl_vr_wa_slot", target="config.onsubmit")
71
+     * @Callback(table="tl_vr_wa_slot", target="fields.time.save", priority=1)
69 72
      */
70
-    public function adjustTime(DataContainer $dc)
73
+    public function checkAndAdjustTime($varValue, DataContainer $dc)
71 74
     {
75
+        /** @var SlotChecker $slotchecker */
76
+        $slotchecker = System::getContainer()->get('vonrotenberg.wa.slot_checker');
77
+
72 78
         // Return if there is no active record (override all) or no start date has been set yet
73 79
         if (!$dc->activeRecord || empty($dc->activeRecord->date))
74 80
         {
75
-            return;
81
+            throw new \Exception($this->translator->trans('ERR.wa_slot_nodate', [], 'contao_tl_vr_wa_slot'));
76 82
         }
77 83
 
78
-        $arrSet['time'] = strtotime(date('Y-m-d', $dc->activeRecord->date) . ' ' . date('H:i:s', $dc->activeRecord->time));
84
+        $start = strtotime(date('Y-m-d', $dc->activeRecord->date) . ' ' . date('H:i:s', $varValue));
85
+        $duration = \intval(Input::post('duration')) !== null ? intval(Input::post('duration'))*60 : $dc->activeRecord->duration*60;
86
+
87
+        if ($slotchecker->checkTimeApplicableForSite($dc->activeRecord->pid,$start,$start+$duration,0,\intval($dc->id)))
88
+        {
89
+            throw new \Exception($this->translator->trans('ERR.wa_slot_conflict', [], 'contao_tl_vr_wa_slot'));
90
+        }
79 91
 
80
-        $this->db->update("tl_vr_wa_slot",$arrSet,['id' => $dc->id]);
92
+        return $start;
81 93
     }
82 94
 }
83 95
new file mode 100644
... ...
@@ -0,0 +1,60 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of contao-weinanlieferung-bundle.
7
+ *
8
+ * (c) vonRotenberg
9
+ *
10
+ * @license commercial
11
+ */
12
+
13
+namespace vonRotenberg\WeinanlieferungBundle;
14
+
15
+use Doctrine\DBAL\Connection;
16
+
17
+class SlotChecker {
18
+
19
+    private $db;
20
+
21
+    public function __construct(Connection $connection) {
22
+        $this->db = $connection;
23
+    }
24
+
25
+    public function checkTimeApplicableForSite(int $siteId, int $startTime, int $endTime, int $buffer=0,int $exceptionId=0): bool {
26
+        // Get existing slots in the timeframe
27
+        $sql = "SELECT COUNT(id) FROM tl_vr_wa_slot
28
+WHERE
29
+	pid = :pid
30
+	AND
31
+	(
32
+		(
33
+			time >= :start
34
+			AND time <= :end
35
+		)
36
+		OR
37
+		(
38
+			time+duration*60 > :start
39
+			AND time+duration*60 <= :end
40
+		)
41
+		OR
42
+		(
43
+			time < :start
44
+			AND time+duration*60 > :end
45
+		)
46
+	)";
47
+        $values = ['pid' => $siteId, 'start' => $startTime-$buffer, 'end' => $endTime+$buffer];
48
+
49
+        if ($exceptionId > 0)
50
+        {
51
+            $sql .= " AND id != :exceptionId";
52
+            $values['exceptionId'] = $exceptionId;
53
+        }
54
+
55
+        $ConflictingSlots = $this->db->prepare($sql)->executeQuery($values);
56
+
57
+        return $ConflictingSlots->fetchOne() == true;
58
+    }
59
+
60
+}