Benjamin Roth authored on18/07/2024 16:43:47
Showing7 changed files
... ...
@@ -8,6 +8,7 @@
8 8
  * @license commercial
9 9
  */
10 10
 
11
+use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlottypesModel;
11 12
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungUnitsModel;
12 13
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLageModel;
13 14
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
... ...
@@ -32,6 +33,7 @@ ArrayUtil::arrayInsert($GLOBALS['BE_MOD'],1,[
32 33
 
33 34
 
34 35
 $GLOBALS['TL_MODELS']['tl_vr_wa_units'] = WeinanlieferungUnitsModel::class;
36
+$GLOBALS['TL_MODELS']['tl_vr_wa_slottypes'] = WeinanlieferungSlottypesModel::class;
35 37
 $GLOBALS['TL_MODELS']['tl_vr_wa_slot'] = WeinanlieferungSlotsModel::class;
36 38
 $GLOBALS['TL_MODELS']['tl_vr_wa_standort'] = WeinanlieferungStandortModel::class;
37 39
 $GLOBALS['TL_MODELS']['tl_vr_wa_rebsorte'] = WeinanlieferungRebsorteModel::class;
... ...
@@ -92,7 +92,8 @@ $GLOBALS['TL_DCA']['tl_vr_wa_slot'] = array
92 92
     'palettes' => array
93 93
     (
94 94
         '__selector__' => array('addEnclosure'),
95
-        'default' => '{time_legend},date,time;{type_legend},behaelter,sorten,lage,ernteart;{info_legend},anmerkungen,addEnclosure;{booking_legend},published,buchbar_ab,buchbar_bis'
95
+//        'default' => '{time_legend},date,time,duration;{type_legend},behaelter,sorten,lage,ernteart;{info_legend},anmerkungen,addEnclosure;{booking_legend},published,buchbar_ab,buchbar_bis'
96
+        'default' => '{time_legend},date,time,duration;{type_legend},behaelter;{info_legend},anmerkungen,addEnclosure;{booking_legend},published,buchbar_ab,buchbar_bis'
96 97
     ),
97 98
 
98 99
     // Subpalettes
... ...
@@ -138,6 +139,21 @@ $GLOBALS['TL_DCA']['tl_vr_wa_slot'] = array
138 139
             'eval'      => array('rgxp' => 'time', 'mandatory' => true, 'tl_class' => 'w50'),
139 140
             'sql'       => "int(10) NULL"
140 141
         ),
142
+        'duration' => array
143
+        (
144
+            'exclude'                 => true,
145
+            'inputType'               => 'text',
146
+            'eval'                    => array
147
+            (
148
+                'mandatory' => true,
149
+                'maxlength' => 4,
150
+                'maxval'    => 1440,
151
+                'minval'    => 1,
152
+                'rgxp'      => 'natural',
153
+                'tl_class' => 'w50'
154
+            ),
155
+            'sql'                     => "int(4) NOT NULL default 0"
156
+        ),
141 157
         'lage'   => array
142 158
         (
143 159
             'exclude'   => true,
... ...
@@ -149,18 +165,18 @@ $GLOBALS['TL_DCA']['tl_vr_wa_slot'] = array
149 165
         ),
150 166
         'behaelter'   => array
151 167
         (
152
-            'exclude'   => true,
153
-            'inputType' => 'select',
154
-            'options_callback'   => function () {
155
-                $range = [];
156
-                for ($i = 1; $i <= 30; $i++)
157
-                {
158
-                    $range[] = $i;
159
-                }
160
-                return $range;
161
-            },
162
-            'eval'      => array('rgxp' => 'natural', 'mandatory' => true, 'includeBlankOption' => true, 'tl_class' => 'w50'),
163
-            'sql'       => "smallint(3) unsigned NOT NULL default 0"
168
+            'exclude'                 => true,
169
+            'inputType'               => 'text',
170
+            'eval'                    => array
171
+            (
172
+                'mandatory' => true,
173
+                'maxlength' => 4,
174
+                'maxval'    => 9999,
175
+                'minval'    => 1,
176
+                'rgxp'      => 'natural',
177
+                'tl_class' => 'w50'
178
+            ),
179
+            'sql'                     => "int(4) NOT NULL default 0"
164 180
         ),
165 181
         'sorten'       => array
166 182
         (
... ...
@@ -104,7 +104,8 @@ $GLOBALS['TL_DCA']['tl_vr_wa_slottypes'] = array
104 104
         'pid' => array
105 105
         (
106 106
             'foreignKey'              => "tl_vr_wa_standort.title",
107
-            'sql'                     => "int(10) unsigned NOT NULL default 0"
107
+            'sql'                     => "int(10) unsigned NOT NULL default 0",
108
+            'relation'                => array('type'=>'belongsTo', 'load'=>'lazy')
108 109
         ),
109 110
         'tstamp' => array
110 111
         (
... ...
@@ -71,7 +71,7 @@ $GLOBALS['TL_DCA']['tl_vr_wa_standort'] = array
71 71
             'edit' => array
72 72
             (
73 73
                 'href'                => 'table=tl_vr_wa_slot',
74
-                'icon'                => 'edit.gif',
74
+                'icon'                => '/bundles/vonrotenbergweinanlieferung/images/icons/calendar.svg',
75 75
             ),
76 76
             'slottypes' => array
77 77
             (
... ...
@@ -12,6 +12,8 @@ $GLOBALS['TL_LANG']['tl_vr_wa_slot']['date'][0] = 'Datum';
12 12
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['date'][1] = 'Der Tag der Anlieferung.';
13 13
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['time'][0] = 'Uhrzeit';
14 14
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['time'][1] = 'Uhrzeit dieses Anlieferungsslots.';
15
+$GLOBALS['TL_LANG']['tl_vr_wa_slot']['duration'][0] = 'Dauer in min.';
16
+$GLOBALS['TL_LANG']['tl_vr_wa_slot']['duration'][1] = 'Die Dauer des Slots.';
15 17
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['behaelter'][0] = 'Behälter';
16 18
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['behaelter'][1] = 'Anzahl der Behälter, die verarbeitet werden können.';
17 19
 $GLOBALS['TL_LANG']['tl_vr_wa_slot']['lage'][0] = 'Lage';
... ...
@@ -43,6 +43,7 @@ use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungLeseartModel;
43 43
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
44 44
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungReservationModel;
45 45
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel;
46
+use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlottypesModel;
46 47
 
47 48
 /**
48 49
  * @Route("%contao.backend.route_prefix%/weinanlieferung/slotassistant", name=self::class, defaults={"_scope" = "backend"})
... ...
@@ -77,28 +78,33 @@ class WeinanlieferungSlotAssistantController extends AbstractController
77 78
 
78 79
     public function __invoke(): Response
79 80
     {
80
-        // Handle ajax request
81
-        if ($_POST && Environment::get('isAjaxRequest'))
82
-        {
83
-            $this->objAjax = new Ajax(Input::post('action'));
84
-            $this->objAjax->executePreActions();
85
-        }
81
+        System::loadLanguageFile('default');
82
+        System::loadLanguageFile('tl_vr_wa_slotassistant');
83
+        Controller::loadDataContainer('tl_vr_wa_slot');
84
+        Controller::loadDataContainer('tl_vr_wa_slotassistant');
86 85
 
87 86
         $GLOBALS['TL_CSS']['cirrus'] = 'bundles/vonrotenbergweinanlieferung/css/backend.css|static';
88 87
         $arrData = [
89 88
             'request_token' => $this->tokenManager->getDefaultTokenValue(),
90 89
             'ref'           => $this->request->attributes->get('_contao_referer_id')
91 90
         ];
92
-        System::loadLanguageFile('default');
93
-        System::loadLanguageFile('tl_vr_wa_slotassistant');
94
-        Controller::loadDataContainer('tl_vr_wa_slot');
95
-        Controller::loadDataContainer('tl_vr_wa_slotassistant');
96 91
 
97
-//        dump($this->getWidgets());
92
+        // Handle ajax request pre actions
93
+        if ($_POST && Environment::get('isAjaxRequest'))
94
+        {
95
+            $this->objAjax = new Ajax(Input::post('action'));
96
+            $this->objAjax->executePreActions();
97
+        }
98
+
99
+        // Form submitted
100
+        if (Input::post('FORM_SUBMIT') == 'wa_slotassistant')
101
+        {
102
+            $this->generateSlots();
103
+        }
98 104
 
99 105
         $arrData['fields'] = $this->getWidgets();
100 106
 
101
-        // AJAX request
107
+        // Handle ajax request post actions
102 108
         if ($_POST && Environment::get('isAjaxRequest'))
103 109
         {
104 110
             $dc = new DC_File('tl_vr_wa_slotassistant');
... ...
@@ -227,7 +233,7 @@ class WeinanlieferungSlotAssistantController extends AbstractController
227 233
                     'help'   => 'Anmerkungen zum Zeitslot. Diese werden bei der Buchung angezeigt.',
228 234
                     'widget' => new TextArea([
229 235
                         'name'      => 'annotation',
230
-                        'mandatory' => true,
236
+                        'mandatory' => false,
231 237
                         'label'     => 'Anmerkungen',
232 238
                         'rte'       => 'tinyMCE'
233 239
                     ])
... ...
@@ -237,7 +243,7 @@ class WeinanlieferungSlotAssistantController extends AbstractController
237 243
                     'help'   => 'Anmerkungen zum Zeitslot. Diese werden bei der Buchung angezeigt.',
238 244
                     'widget' => new FileTree([
239 245
                         'name'        => 'enclosure',
240
-                        'mandatory'   => true,
246
+                        'mandatory'   => false,
241 247
                         'label'       => 'Anmerkungen',
242 248
                         'multiple'    => true,
243 249
                         'fieldType'   => 'checkbox',
... ...
@@ -341,11 +347,6 @@ class WeinanlieferungSlotAssistantController extends AbstractController
341 347
 
342 348
                     unset($file, $type, $pickerBuilder, $fileBrowserTypes, $fileBrowserType);
343 349
                 }
344
-
345
-                if (Input::post('FORM_SUBMIT') == 'wa_slotassistant')
346
-                {
347
-                    dump($field['widget']->validate());
348
-                }
349 350
             }
350 351
         }
351 352
 
... ...
@@ -371,4 +372,97 @@ class WeinanlieferungSlotAssistantController extends AbstractController
371 372
 
372 373
         return $arrOptions;
373 374
     }
375
+
376
+    protected function validateForm()
377
+    {
378
+        $blnSubmit = false;
379
+        if (Input::post('FORM_SUBMIT') == 'wa_slotassistant')
380
+        {
381
+            $blnSubmit = true;
382
+            foreach ($this->getWidgets() as $group => $fields)
383
+            {
384
+                foreach ($fields as $field)
385
+                {
386
+                    $field['widget']->validate();
387
+                    if ($field['widget']->hasErrors())
388
+                    {
389
+                        $blnSubmit = false;
390
+                    }
391
+                }
392
+            }
393
+        }
394
+        return $blnSubmit;
395
+    }
396
+
397
+    protected function generateSlots()
398
+    {
399
+        if (!Input::post('FORM_SUBMIT') == 'wa_slotassistant' || !$this->validateForm())
400
+        {
401
+            return;
402
+        }
403
+
404
+        if (
405
+            ($SlotType = WeinanlieferungSlottypesModel::findByPk(Input::post('slotType'))) === null
406
+            || ($Standort = $SlotType->getRelated('pid')) === null
407
+            || !\is_array(Input::post('timeframe'))
408
+        )
409
+        {
410
+            return;
411
+        }
412
+
413
+        // Get timespans
414
+        foreach (Input::post('timeframe') as $timeframe)
415
+        {
416
+            if (
417
+                !isset($timeframe['date_start'])
418
+                || !isset($timeframe['date_end'])
419
+            )
420
+            {
421
+                continue;
422
+            }
423
+
424
+            $StartDate = new Date($timeframe['date_start'], Date::getNumericDatimFormat());
425
+            $EndDate = new Date($timeframe['date_end'], Date::getNumericDatimFormat());
426
+
427
+            $intStart  = $StartDate->tstamp;
428
+            $intEnd  = $EndDate->tstamp;
429
+            $intBuffer = intval(Input::post('buffer')) * 60;
430
+            $intDuration = (int) $SlotType->duration*60;
431
+            $arrTimes = [];
432
+            $arrStartTimes = [];
433
+            $arrEndTimes = [];
434
+
435
+            // Get existing slots in the timeframe
436
+            $ExistingSlots = $this->db->prepare("SELECT id, date, time as 'start', time+duration as 'end', duration FROM tl_vr_wa_slot WHERE pid = ? AND (time >= ? OR time+$intDuration+$intBuffer >= ?) AND (time <= ? OR time+$intDuration+$intBuffer <= ?) ORDER BY time")
437
+                                      ->executeQuery([$Standort->id, $intStart, $intStart, $intEnd, $intEnd]);
438
+
439
+            if ($ExistingSlots->rowCount())
440
+            {
441
+                foreach ($ExistingSlots->fetchAllAssociative() as $slot)
442
+                {
443
+                    $arrTimes[$slot['start']] = [
444
+                        'start' => $slot['start'],
445
+                        'end'  => $slot['end']
446
+                    ];
447
+                    $arrStartTimes[] = $slot['start'];
448
+                    $arrEndTimes[] = $slot['end'];
449
+                }
450
+            }
451
+
452
+            $intTime = $intStart;
453
+            while ($intTime < $intEnd-$intDuration)
454
+            {
455
+                dump(Date::parse(Date::getNumericDatimFormat(),$intTime));
456
+                $intTime = $intTime + $intDuration + $intBuffer;
457
+
458
+                /** Todo:
459
+                 * Check time against start and stop times and take buffer into account.
460
+                 * If theres a conflict, determine the next possible start time and check again.
461
+                 */
462
+            }
463
+
464
+            //$ExistingSlots = $this->db->prepare("SELECT id, date, time, duration FROM tl_vr_wa_slot WHERE pid = ? AND (time >= ? OR time+duration*60+$intBuffer >= ?) AND (time <= ? OR time+duration*60+$intBuffer <= ?)")
465
+
466
+        }
467
+    }
374 468
 }
375 469
new file mode 100644
... ...
@@ -0,0 +1,24 @@
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\Model;
14
+
15
+use Contao\Model;
16
+
17
+class WeinanlieferungSlottypesModel extends Model
18
+{
19
+    /**
20
+     * Table name
21
+     * @var string
22
+     */
23
+    protected static $strTable = 'tl_vr_wa_slottypes';
24
+}