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