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"
... ...
@@ -43,3 +43,7 @@ $GLOBALS['TL_LANG']['tl_vr_wa_slot']['info_legend'] = 'Zusätzliche Informatione
43 43
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['booking_legend'] = 'Buchbarkeits-Einstellungen';
44 44
 
45 45
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['back'] = 'Zurück';
46
+
47
+
48
+$GLOBALS['TL_LANG']['ERR']['wa_slot_nodate'] = 'Sie müssen ein gültiges Datum angeben';
49
+$GLOBALS['TL_LANG']['ERR']['wa_slot_conflict'] = 'Es besteht ein Konflikt mit einem bereits bestehenden Zeitslot';
... ...
@@ -15,12 +15,15 @@ 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 Symfony\Contracts\Translation\TranslatorInterface;
21 23
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel;
22 24
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
23 25
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel;
26
+use vonRotenberg\WeinanlieferungBundle\SlotChecker;
24 27
 
25 28
 class WeinanlieferungSlotContainerListener
26 29
 {
... ...
@@ -72,18 +75,27 @@ class WeinanlieferungSlotContainerListener
72 75
     }
73 76
 
74 77
     /**
75
-     * @Callback(table="tl_vr_wa_slot", target="config.onsubmit")
78
+     * @Callback(table="tl_vr_wa_slot", target="fields.time.save", priority=1)
76 79
      */
77
-    public function adjustTime(DataContainer $dc)
80
+    public function checkAndAdjustTime($varValue, DataContainer $dc)
78 81
     {
82
+        /** @var SlotChecker $slotchecker */
83
+        $slotchecker = System::getContainer()->get('vonrotenberg.wa.slot_checker');
84
+
79 85
         // Return if there is no active record (override all) or no start date has been set yet
80 86
         if (!$dc->activeRecord || empty($dc->activeRecord->date))
81 87
         {
82
-            return;
88
+            throw new \Exception($this->translator->trans('ERR.wa_slot_nodate', [], 'contao_tl_vr_wa_slot'));
83 89
         }
84 90
 
85
-        $arrSet['time'] = strtotime(date('Y-m-d', $dc->activeRecord->date) . ' ' . date('H:i:s', $dc->activeRecord->time));
91
+        $start = strtotime(date('Y-m-d', $dc->activeRecord->date) . ' ' . date('H:i:s', $varValue));
92
+        $duration = \intval(Input::post('duration')) !== null ? intval(Input::post('duration'))*60 : $dc->activeRecord->duration*60;
93
+
94
+        if ($slotchecker->checkTimeApplicableForSite($dc->activeRecord->pid,$start,$start+$duration,0,\intval($dc->id)))
95
+        {
96
+            throw new \Exception($this->translator->trans('ERR.wa_slot_conflict', [], 'contao_tl_vr_wa_slot'));
97
+        }
86 98
 
87
-        $this->db->update("tl_vr_wa_slot",$arrSet,['id' => $dc->id]);
99
+        return $start;
88 100
     }
89 101
 }
90 102
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
+}