... | ... |
@@ -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 |
( |
... | ... |
@@ -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 |
+} |