Skip to content
Snippets Groups Projects
Commit 8fef8bc3 authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms
Browse files

fixes #4320, fixes #1871

Closes #4320 and #1871

Merge request studip/studip!3125
parent a629426a
No related branches found
No related tags found
No related merge requests found
...@@ -165,13 +165,19 @@ class Consultation_AdminController extends ConsultationController ...@@ -165,13 +165,19 @@ class Consultation_AdminController extends ConsultationController
CSRFProtection::verifyUnsafeRequest(); CSRFProtection::verifyUnsafeRequest();
try { try {
$interval = Request::int('interval');
$start = $this->getDateAndTime('start'); $start = $this->getDateAndTime('start');
$end = $this->getDateAndTime('end'); $end = $this->getDateAndTime($interval === 0 ? 'start' : 'end', 'end');
if (date('Hi', $end) <= date('Hi', $start)) { if (date('Hi', $end) <= date('Hi', $start)) {
throw new InvalidArgumentException(_('Die Endzeit liegt vor der Startzeit!')); throw new InvalidArgumentException(_('Die Endzeit liegt vor der Startzeit!'));
} }
$dow = Request::int('day-of-week');
if ($interval === 0) {
$dow = date('w', $start);
}
// Determine duration of a slot and pause times // Determine duration of a slot and pause times
$duration = Request::int('duration'); $duration = Request::int('duration');
$pause_time = Request::bool('pause') ? Request::int('pause_time') : null; $pause_time = Request::bool('pause') ? Request::int('pause_time') : null;
...@@ -187,8 +193,8 @@ class Consultation_AdminController extends ConsultationController ...@@ -187,8 +193,8 @@ class Consultation_AdminController extends ConsultationController
$slot_count = ConsultationBlock::countSlots( $slot_count = ConsultationBlock::countSlots(
$start, $start,
$end, $end,
Request::int('day-of-week'), $dow,
Request::int('interval'), $interval,
$duration, $duration,
$pause_time, $pause_time,
$pause_duration $pause_duration
...@@ -202,8 +208,8 @@ class Consultation_AdminController extends ConsultationController ...@@ -202,8 +208,8 @@ class Consultation_AdminController extends ConsultationController
$this->range, $this->range,
$start, $start,
$end, $end,
Request::int('day-of-week'), $dow,
Request::int('interval') $interval
); );
$stored = 0; $stored = 0;
...@@ -872,15 +878,19 @@ class Consultation_AdminController extends ConsultationController ...@@ -872,15 +878,19 @@ class Consultation_AdminController extends ConsultationController
} }
} }
private function getDateAndTime($index) private function getDateAndTime(string $index, string $index_time = null)
{ {
if (!Request::submitted("{$index}-date") || !Request::submitted("{$index}-time")) { if ($index_time === null) {
$index_time = $index;
}
if (!Request::submitted("{$index}-date") || !Request::submitted("{$index_time}-time")) {
throw new Exception("Date with index '{$index}' was not submitted properly"); throw new Exception("Date with index '{$index}' was not submitted properly");
} }
return strtotime(implode(' ', [ return strtotime(implode(' ', [
Request::get("{$index}-date"), Request::get("{$index}-date"),
Request::get("{$index}-time") Request::get("{$index_time}-time")
])); ]));
} }
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
<?= Icon::create('add')->asImg(tooltip2(_('Termin reservieren'))) ?> <?= Icon::create('add')->asImg(tooltip2(_('Termin reservieren'))) ?>
</a> </a>
<? else: ?> <? else: ?>
<?= Icon::create('add', Icon::ROLE_INACTIVE)->asImg(tooltip2(_('Dieser Termin ist für Buchungen gesperrt.'))) ?> <?= Icon::create('decline', Icon::ROLE_INACTIVE)->asImg(tooltip2(_('Dieser Termin ist für Buchungen gesperrt.'))) ?>
<? endif; ?> <? endif; ?>
</td> </td>
</tr> </tr>
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
<?= Icon::create('add')->asImg(tooltip2(_('Termin reservieren'))) ?> <?= Icon::create('add')->asImg(tooltip2(_('Termin reservieren'))) ?>
</a> </a>
<? else: ?> <? else: ?>
<?= Icon::create('add', Icon::ROLE_INACTIVE)->asImg(tooltip2(_('Dieser Termin ist für Buchungen gesperrt.'))) ?> <?= Icon::create('decline', Icon::ROLE_INACTIVE)->asImg(tooltip2(_('Dieser Termin ist für Buchungen gesperrt.'))) ?>
<? endif; ?> <? endif; ?>
</td> </td>
</tr> </tr>
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
* @property SimpleORMapCollection|ConsultationEvent[] $events has_many ConsultationEvent * @property SimpleORMapCollection|ConsultationEvent[] $events has_many ConsultationEvent
* @property ConsultationBlock $block belongs_to ConsultationBlock * @property ConsultationBlock $block belongs_to ConsultationBlock
* @property ConsultationSlot|null $previous_slot has_one ConsultationSlot * @property ConsultationSlot|null $previous_slot has_one ConsultationSlot
* @property ConsultationSlot|null $next_slot has_one ConsultationSlot
* @property-read mixed $has_bookings additional field * @property-read mixed $has_bookings additional field
* @property-read mixed $is_expired additional field * @property-read mixed $is_expired additional field
*/ */
...@@ -48,8 +49,12 @@ class ConsultationSlot extends SimpleORMap ...@@ -48,8 +49,12 @@ class ConsultationSlot extends SimpleORMap
'on_delete' => 'delete', 'on_delete' => 'delete',
]; ];
$config['has_one']['previous_slot'] = [ $config['has_one']['previous_slot'] = [
'class_name' => ConsultationSlot::class, 'class_name' => ConsultationSlot::class,
'foreign_key' => 'previous_slot_id', 'foreign_key' => 'previous_slot_id',
];
$config['has_one']['next_slot'] = [
'class_name' => ConsultationSlot::class,
'assoc_func' => 'findOneByPrevious_slot_id',
]; ];
$config['registered_callbacks']['before_create'][] = function (ConsultationSlot $slot) { $config['registered_callbacks']['before_create'][] = function (ConsultationSlot $slot) {
...@@ -183,14 +188,15 @@ class ConsultationSlot extends SimpleORMap ...@@ -183,14 +188,15 @@ class ConsultationSlot extends SimpleORMap
/** /**
* Returns whether the slot is bookable for the given user_id * Returns whether the slot is bookable for the given user_id
*/ */
public function isBookable(?string $user_id = null): bool public function isBookable(): bool
{ {
return !$this->isOccupied($user_id) return !$this->isOccupied()
&& !$this->isLocked() && !$this->isLocked()
&& !( && (
$this->block->consecutive !$this->block->consecutive
&& $this->previous_slot || !$this->block->has_bookings
&& !$this->previous_slot->isOccupied() || ($this->previous_slot && $this->previous_slot->isOccupied())
|| ($this->next_slot && $this->next_slot->isOccupied())
); );
} }
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<label :class="{'col-3': !isSingleDay}"> <label :class="{'col-3': !isSingleDay}">
<span class="required">{{ $gettext('Intervall') }}</span> <span class="required">{{ $gettext('Intervall') }}</span>
<select required name="interval" v-model="interval"> <select required name="interval" v-model.number="interval">
<option v-for="(label, value) in intervals" :key="value" :value="value"> <option v-for="(label, value) in intervals" :key="value" :value="value">
{{ label }} {{ label }}
</option> </option>
...@@ -40,9 +40,9 @@ ...@@ -40,9 +40,9 @@
<label class="col-3" v-if="!isSingleDay"> <label class="col-3" v-if="!isSingleDay">
<span class="required">{{ $gettext('Am Wochentag') }}</span> <span class="required">{{ $gettext('Am Wochentag') }}</span>
<select required name="day-of-week" v-model="dayOfWeek"> <select required name="day-of-week" @change="evt => dayOfWeek = parseInt(evt.target.value, 10)">
<option v-for="(label, value) in daysOfTheWeek" :value="value" :key="value"> <option v-for="dow in daysOfTheWeek" :value="dow.key" :key="dow.key" :selected="dayOfWeek === dow.key">
{{ label }} {{ dow.label }}
</option> </option>
</select> </select>
</label> </label>
...@@ -359,15 +359,15 @@ export default { ...@@ -359,15 +359,15 @@ export default {
return STUDIP.CSRF_TOKEN; return STUDIP.CSRF_TOKEN;
}, },
daysOfTheWeek() { daysOfTheWeek() {
return { return [
1: this.$gettext('Montag'), {key: 1, label: this.$gettext('Montag')},
2: this.$gettext('Dienstag'), {key: 2, label: this.$gettext('Dienstag')},
3: this.$gettext('Mittwoch'), {key: 3, label: this.$gettext('Mittwoch')},
4: this.$gettext('Donnerstag'), {key: 4, label: this.$gettext('Donnerstag')},
5: this.$gettext('Freitag'), {key: 5, label: this.$gettext('Freitag')},
6: this.$gettext('Samstag'), {key: 6, label: this.$gettext('Samstag')},
0: this.$gettext('Sonntag'), {key: 0, label: this.$gettext('Sonntag')},
}; ];
}, },
intervals() { intervals() {
return { return {
...@@ -385,7 +385,7 @@ export default { ...@@ -385,7 +385,7 @@ export default {
return this.rangeType === 'Institute'; return this.rangeType === 'Institute';
}, },
isSingleDay() { isSingleDay() {
return this.interval === '0'; return this.interval === 0;
}, },
needsConfirmation() { needsConfirmation() {
return this.slotCount > this.slotCountThreshold; return this.slotCount > this.slotCountThreshold;
...@@ -419,7 +419,7 @@ export default { ...@@ -419,7 +419,7 @@ export default {
errors.push(this.$gettext('Die Endzeit liegt vor der Startzeit!')); errors.push(this.$gettext('Die Endzeit liegt vor der Startzeit!'));
} }
if (this.startDate > this.endDate) { if (this.interval > 0 && this.startDate > this.endDate) {
errors.push(this.$gettext('Das Enddatum liegt vor dem Startdatum!')); errors.push(this.$gettext('Das Enddatum liegt vor dem Startdatum!'));
} }
...@@ -457,7 +457,7 @@ export default { ...@@ -457,7 +457,7 @@ export default {
}, },
watch: { watch: {
interval(current) { interval(current) {
if (current === '0') { if (current === 0) {
this.endDate = new Date(this.startDate); this.endDate = new Date(this.startDate);
} }
}, },
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment