ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilBookingReservationsGUI.php
Go to the documentation of this file.
1 <?php
2 
24 {
26  protected \ILIAS\DI\UIServices $ui;
27  protected \ILIAS\BookingManager\InternalService $service;
28  protected array $raw_post_data;
29  protected \ILIAS\BookingManager\StandardGUIRequest $book_request;
31  protected int $context_obj_id;
32  protected ilCtrl $ctrl;
34  protected ilLanguage $lng;
36  protected ilTabsGUI $tabs_gui;
37  protected ilObjUser $user;
39  protected int $ref_id;
40  protected int $book_obj_id;
41  protected int $pbooked_user;
42  protected string $reservation_id; // see BookingReservationDBRepo, obj_user_(slot)_context
43  protected int $booked_user;
44 
45  public function __construct(
46  ilObjBookingPool $pool,
48  int $context_obj_id = 0
49  ) {
50  global $DIC;
51 
52  $this->tpl = $DIC->ui()->mainTemplate();
53  $this->pool = $pool;
54  $this->ctrl = $DIC->ctrl();
55  $this->ref_id = $pool->getRefId();
56  $this->lng = $DIC->language();
57  $this->access = $DIC->access();
58  $this->tabs_gui = $DIC->tabs();
59  $this->help = $help;
60  $this->user = $DIC->user();
61  $this->book_request = $DIC->bookingManager()
62  ->internal()
63  ->gui()
64  ->standardRequest();
65  $this->service = $DIC->bookingManager()->internal();
66  $this->ui = $DIC->ui();
67  $this->toolbar = $DIC->toolbar();
68 
69  $this->book_obj_id = $this->book_request->getObjectId();
70 
71  $this->context_obj_id = $context_obj_id;
72 
73  // user who's reservation is being tackled (e.g. canceled)
74  $this->booked_user = $this->book_request->getBookedUser();
75  if ($this->booked_user === 0) {
76  $this->booked_user = $DIC->user()->getId();
77  }
78  // we get this from the reservation screen
79  $this->reservation_id = $this->book_request->getReservationId();
80 
81  $this->ctrl->saveParameter($this, ["object_id", "bkusr"]);
82 
83  if ($this->book_request->getObjectId() > 0 && ilBookingObject::lookupPoolId($this->book_request->getObjectId()) !== $this->pool->getId()) {
84  throw new ilException("Booking Object ID does not match Booking Pool.");
85  }
86 
87  $this->raw_post_data = $DIC->http()->request()->getParsedBody();
88  }
89 
93  protected function getLogReservationIds(): array
94  {
95  $mrsv = $this->book_request->getReservationIds();
96  if (count($mrsv) > 0) {
97  return $mrsv;
98  }
99  if ($this->reservation_id > 0) {
100  return array($this->reservation_id);
101  }
102  return [];
103  }
104 
105  public function executeCommand(): void
106  {
107  $ctrl = $this->ctrl;
108 
109  $next_class = $ctrl->getNextClass($this);
110  $cmd = $ctrl->getCmd("log");
111 
112  switch ($next_class) {
113  default:
114  if (in_array($cmd, array("log", "logDetails", "changeStatusObject", "rsvConfirmCancelUser", "rsvCancelUser",
115  "applyLogFilter", "resetLogFilter", "rsvConfirmCancel", "rsvCancel", "back", "rsvConfirmDelete", "rsvDelete", "confirmResetRun", "resetRun"))) {
116  $this->$cmd();
117  }
118  }
119  }
120 
121  protected function setHelpId(string $a_id): void
122  {
123  $this->help->setHelpId($a_id);
124  }
125 
129  public function log(): void
130  {
131  $tpl = $this->tpl;
133  $table = $this->getReservationsTable();
134  $tpl->setContent($table->getHTML());
135  }
136 
140  protected function getReservationsTable(
141  ?string $reservation_id = null
143  $show_all = ($this->checkPermissionBool('write') || $this->pool->hasPublicLog());
144 
145  $filter = null;
146  if ($this->book_obj_id > 0) {
147  $filter["object"] = $this->book_obj_id;
148  }
149  // coming from participants tab to cancel reservations.
150  if ($this->book_request->getUserId() > 0) {
151  $filter["user_id"] = $this->book_request->getUserId();
152  }
153  $context_filter = ($this->context_obj_id > 0)
154  ? [$this->context_obj_id]
155  : null;
156 
158  $this,
159  'log',
160  $this->ref_id,
161  $this->pool->getId(),
162  $show_all,
163  ($this->pool->getScheduleType() === ilObjBookingPool::TYPE_FIX_SCHEDULE),
164  $filter,
165  $reservation_id,
166  $context_filter
167  );
168  }
169 
170  public function logDetails(): void
171  {
172  $tpl = $this->tpl;
173 
174  $this->tabs_gui->clearTargets();
175  $this->tabs_gui->setBackTarget(
176  $this->lng->txt("back"),
177  $this->ctrl->getLinkTarget($this, "log")
178  );
179 
180  $table = $this->getReservationsTable($this->reservation_id);
181  $tpl->setContent($table->getHTML());
182  }
183 
187  public function changeStatusObject(): void
188  {
189  $rsv_ids = $this->book_request->getReservationIds();
190  if (count($rsv_ids) === 0) {
191  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
192  $this->log();
193  }
194 
195  if ($this->checkPermissionBool('write')) {
197  $rsv_ids,
198  $this->book_request->getStatus()
199  );
200  }
201 
202  $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
203  $this->ctrl->redirect($this, 'log');
204  }
205 
206  public function applyLogFilter(): void
207  {
208  $table = $this->getReservationsTable();
209  $table->resetOffset();
210  $table->writeFilterToSession();
211  $this->log();
212  }
213 
214  public function resetLogFilter(): void
215  {
216  $table = $this->getReservationsTable();
217  $table->resetOffset();
218  $table->resetFilter();
219  $this->log();
220  }
221 
222  protected function checkPermissionBool(string $a_perm): bool
223  {
224  return $this->access->checkAccess($a_perm, "", $this->ref_id);
225  }
226 
227  //
228  // Cancelation reservations
229  //
230 
240  public function rsvConfirmCancelUser(): void
241  {
242  $ilCtrl = $this->ctrl;
243  $lng = $this->lng;
244  $tpl = $this->tpl;
246  if (!$id) {
247  return;
248  }
249 
250  $this->setHelpId("cancel_booking");
251 
252  $conf = new ilConfirmationGUI();
253  $conf->setFormAction($ilCtrl->getFormAction($this));
254  $conf->setHeaderText($lng->txt('book_confirm_cancel'));
255 
256  $type = new ilBookingObject($id);
257  $conf->addItem('object_id', $id, $type->getTitle());
258  $conf->setConfirm($lng->txt('book_set_cancel'), 'rsvCancelUser');
259  $conf->setCancel($lng->txt('cancel'), 'back');
260 
261  $tpl->setContent($conf->getHTML());
262  }
263 
267  public function rsvCancelUser(): void
268  {
269  $lng = $this->lng;
270 
272  $user_id = $this->booked_user;
273 
274  if (!$id || !$user_id) {
275  return;
276  }
277 
279  $id = current($ids);
280  $obj = new ilBookingReservation($id);
281  if ($obj->getUserId() !== $user_id) {
282  $this->tpl->setOnScreenMessage('failure', $lng->txt('permission_denied'), true);
283  $this->back();
284  }
285 
287  $obj->update();
288 
289  $this->tpl->setOnScreenMessage('success', $lng->txt('settings_saved'), true);
290  $this->back();
291  }
292 
296  protected function back(): void
297  {
298  $this->ctrl->redirect($this, "log");
299  }
300 
304  public function rsvConfirmCancel(): void
305  {
306  $ilCtrl = $this->ctrl;
307  $lng = $this->lng;
308  $tpl = $this->tpl;
310 
311  $ids = $this->getLogReservationIds();
312  if (count($ids) === 0) {
313  $this->back();
314  }
315  $max = array();
316  foreach ($ids as $idx => $id) {
317  if (!is_numeric($id)) {
318  [$obj_id, $user_id, $from, $to] = explode("_", $id);
319 
320  $valid_ids = array();
321  foreach (ilBookingObject::getList($this->pool->getId()) as $item) {
322  $valid_ids[$item["booking_object_id"]] = $item["title"];
323  }
324  if (array_key_exists($obj_id, $valid_ids) && $from > time() && ($this->checkPermissionBool("write") || (int) $user_id === $ilUser->getId())) {
325  $rsv_ids = ilBookingReservation::getCancelDetails($obj_id, $user_id, $from, $to);
326  if (!count($rsv_ids)) {
327  unset($ids[$idx]);
328  }
329  if (count($rsv_ids) > 1) {
330  $max[$id] = count($rsv_ids);
331  $ids[$idx] = $rsv_ids;
332  } else {
333  // only 1 in group? treat as normal reservation
334  $ids[$idx] = array_shift($rsv_ids);
335  }
336  } else {
337  unset($ids[$idx]);
338  }
339  }
340  }
341 
342  if (!is_array($ids) || !count($ids)) {
343  $this->ctrl->redirect($this, 'log');
344  }
345 
346  // show form instead
347  if (count($max) && max($max) > 1) {
348  $this->rsvConfirmCancelAggregation($ids);
349  return;
350  }
351 
352  $this->tabs_gui->clearTargets();
353  $this->tabs_gui->setBackTarget(
354  $lng->txt("back"),
355  $ilCtrl->getLinkTargetByClass("ilBookingReservationsGUI", "")
356  );
357 
358  $this->setHelpId("cancel_booking");
359 
360  $conf = new ilConfirmationGUI();
361  $conf->setFormAction($ilCtrl->getFormAction($this, 'rsvCancel'));
362  $conf->setHeaderText($lng->txt('book_confirm_cancel'));
363  $conf->setConfirm($lng->txt('book_set_cancel'), 'rsvCancel');
364  $conf->setCancel($lng->txt('cancel'), 'back');
365 
366  foreach ($ids as $id) {
367  $rsv = new ilBookingReservation($id);
368  $obj = new ilBookingObject($rsv->getObjectId());
369 
370  $details = $obj->getTitle();
371  if ($this->pool->getScheduleType() !== ilObjBookingPool::TYPE_NO_SCHEDULE) {
372  $details .= ", " . ilDatePresentation::formatPeriod(
373  new ilDateTime($rsv->getFrom(), IL_CAL_UNIX),
374  new ilDateTime($rsv->getTo() + 1, IL_CAL_UNIX)
375  );
376  }
377 
378  $conf->addItem('rsv_id[]', $id, $details);
379  }
380 
381  $tpl->setContent($conf->getHTML());
382  }
383 
384 
389  public function rsvConfirmCancelAggregation(array $a_ids = null): void
390  {
391  $tpl = $this->tpl;
392  $ilCtrl = $this->ctrl;
393  $lng = $this->lng;
394 
395  $this->tabs_gui->clearTargets();
396  $this->tabs_gui->setBackTarget(
397  $lng->txt("back"),
398  $ilCtrl->getLinkTarget($this, "log")
399  );
400 
401  $this->setHelpId("cancel_booking");
402 
403  // #13511
404  $this->tpl->setOnScreenMessage('question', $lng->txt("book_confirm_cancel"));
405 
406  $form = $this->rsvConfirmCancelAggregationForm($a_ids);
407 
408  $tpl->setContent($form->getHTML());
409  }
410 
415  array $a_ids
416  ): ilPropertyFormGUI {
417  $form = new ilPropertyFormGUI();
418  $form->setFormAction($this->ctrl->getFormAction($this, "rsvCancel"));
419  $form->setTitle($this->lng->txt("book_confirm_cancel_aggregation"));
420 
422 
423  foreach ($a_ids as $idx => $ids) {
424  $first = $ids;
425  if (is_array($ids)) {
426  $first = array_shift($first);
427  }
428 
429  $rsv = new ilBookingReservation($first);
430  $obj = new ilBookingObject($rsv->getObjectId());
431 
432  $caption = $obj->getTitle() . ", " . ilDatePresentation::formatPeriod(
433  new ilDateTime($rsv->getFrom(), IL_CAL_UNIX),
434  new ilDateTime($rsv->getTo() + 1, IL_CAL_UNIX)
435  );
436 
437  // #17869
438  if (is_array($ids)) {
439  $caption .= " (" . count($ids) . ")";
440  }
441 
442  $item = new ilNumberInputGUI($caption, "rsv_id_" . $idx);
443  $item->setRequired(true);
444  $item->setMinValue(0);
445  $item->setSize(4);
446  $form->addItem($item);
447 
448  if (is_array($ids)) {
449  $item->setMaxValue(count($ids));
450 
451  foreach ($ids as $id) {
452  $hidden = new ilHiddenInputGUI("rsv_aggr[" . $idx . "][]");
453  $hidden->setValue($id);
454  $form->addItem($hidden);
455  }
456  } else {
457  $item->setMaxValue(1);
458 
459  $hidden = new ilHiddenInputGUI("rsv_aggr[" . $idx . "]");
460  $hidden->setValue($ids);
461  $form->addItem($hidden);
462  }
463 
464  if ($this->book_request->getCancelNr($idx)) {
465  $item->setValue($this->book_request->getCancelNr($idx));
466  }
467  }
468 
469  $form->addCommandButton("rsvCancel", $this->lng->txt("confirm"));
470  $form->addCommandButton("log", $this->lng->txt("cancel"));
471 
472  return $form;
473  }
474 
478  public function rsvCancel(): void
479  {
481  $tpl = $this->tpl;
482  $lng = $this->lng;
483  $ilCtrl = $this->ctrl;
484 
485  // simple version of reservation id
486  $ids = $this->book_request->getReservationIds();
487 
488  $rsv_aggr = $this->raw_post_data["rsv_aggr"] ?? null;
489  // aggregated version: determine reservation ids
490  if (!is_null($rsv_aggr)) {
491  $form = $this->rsvConfirmCancelAggregationForm($rsv_aggr);
492  if (!$form->checkInput()) {
493  $this->tabs_gui->clearTargets();
494  $this->tabs_gui->setBackTarget(
495  $lng->txt("back"),
496  $ilCtrl->getLinkTarget($this, "log")
497  );
498 
499  $tpl->setContent($form->getHTML());
500  return;
501  }
502 
503  $ids = array();
504  foreach ($rsv_aggr as $idx => $aggr_ids) {
505  $max = $this->book_request->getCancelNr($idx);
506  if ($max) {
507  if (!is_array($aggr_ids)) {
508  $ids[] = $aggr_ids;
509  } else {
510  $aggr_ids = array_slice($aggr_ids, 0, $max);
511  $ids = array_merge($ids, $aggr_ids);
512  }
513  }
514  }
515  }
516 
517  // for all reservation ids -> set reservation status to cancelled (and remove calendar entry)
518  if ($ids) {
519  foreach ($ids as $id) {
520  $res = new ilBookingReservation($id);
521 
522  // either write permission or own booking
523  $cancel_allowed_per_read = ($this->checkPermissionBool("read") && ($res->getUserId() === $ilUser->getId()));
524  $cancel_allowed_per_write = ($this->checkPermissionBool("write"));
525  if (!$cancel_allowed_per_read && !$cancel_allowed_per_write) {
526  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
527  $this->ctrl->redirect($this, 'log');
528  }
529 
531  $res->update();
532 
533  if ($this->pool->getScheduleType() !== ilObjBookingPool::TYPE_NO_SCHEDULE) {
534  // remove user calendar entry (#11086)
535  $cal_entry_id = $res->getCalendarEntry();
536  if ($cal_entry_id) {
537  $entry = new ilCalendarEntry($cal_entry_id);
538  $entry->delete();
539  }
540  }
541  }
542  }
543 
544  $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'));
545  $this->log();
546  }
547 
548  public function rsvConfirmDelete(): void
549  {
550  global $DIC;
551  if (!$this->checkPermissionBool("write")) {
552  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
553  $this->ctrl->redirect($this, 'log');
554  }
555 
556  $ids = $this->getLogReservationIds();
557  if (count($ids) === 0) {
558  $this->back();
559  }
560 
561  $this->tabs_gui->clearTargets();
562  $this->tabs_gui->setBackTarget(
563  $this->lng->txt("back"),
564  $this->ctrl->getLinkTarget($this, "log")
565  );
566 
567  $conf = new ilConfirmationGUI();
568  $conf->setFormAction($this->ctrl->getFormAction($this, 'rsvDelete'));
569  $conf->setHeaderText($this->lng->txt('book_confirm_delete'));
570  $conf->setConfirm($this->lng->txt('book_set_delete'), 'rsvDelete');
571  $conf->setCancel($this->lng->txt('cancel'), 'log');
572 
573  if ($this->pool->getScheduleType() === ilObjBookingPool::TYPE_FIX_SCHEDULE) {
574  foreach ($ids as $idx => $id) {
575  [$obj_id, $user_id, $from, $to] = explode("_", $id);
576  $rsv_ids = ilBookingReservation::getCancelDetails($obj_id, $user_id, $from, $to);
577  $rsv_id = $rsv_ids[0];
578 
579  $rsv = new ilBookingReservation($rsv_id);
580  $obj = new ilBookingObject($rsv->getObjectId());
581 
582  $details = sprintf($this->lng->txt('X_reservations_of'), count($rsv_ids)) . ' ' . $obj->getTitle();
583  $details .= ", " . ilDatePresentation::formatPeriod(
584  new ilDateTime($rsv->getFrom(), IL_CAL_UNIX),
585  new ilDateTime($rsv->getTo() + 1, IL_CAL_UNIX)
586  );
587  $conf->addItem('mrsv[]', $id, $details);
588  }
589  } else {
590  foreach ($ids as $idx => $rsv_id) {
591  $rsv = new ilBookingReservation($rsv_id);
592  $obj = new ilBookingObject($rsv->getObjectId());
593  $details = sprintf($this->lng->txt('X_reservations_of'), 1) . ' ' . $obj->getTitle();
594  $conf->addItem('mrsv[]', $rsv_id, $details);
595  }
596  }
597  $this->tpl->setContent($conf->getHTML());
598  }
599 
600  public function rsvDelete(): void
601  {
602  global $DIC;
603  $get = $DIC->http()->request()->getParsedBody()['mrsv'];
604  if ($get) {
605  foreach ($get as $id) {
606  if ($this->pool->getScheduleType() == ilObjBookingPool::TYPE_FIX_SCHEDULE) {
607  list($obj_id, $user_id, $from, $to) = explode("_", $id);
608  $rsv_ids = ilBookingReservation::getCancelDetails($obj_id, $user_id, $from, $to);
609  } else {
610  $rsv_ids = [$id];
611  }
612 
613  foreach ($rsv_ids as $rsv_id) {
614  $res = new ilBookingReservation($rsv_id);
615  $obj = new ilBookingObject($res->getObjectId());
616  if (!$this->checkPermissionBool("write") || $obj->getPoolId() !== $this->pool->getId()) {
617  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
618  $this->ctrl->redirect($this, 'log');
619  }
620  if ($this->pool->getScheduleType() !== ilObjBookingPool::TYPE_NO_SCHEDULE) {
621  $cal_entry_id = $res->getCalendarEntry();
622  if ($cal_entry_id) {
623  $entry = new ilCalendarEntry($cal_entry_id);
624  $entry->delete();
625  }
626  }
627  $res->delete();
628  }
629  }
630  }
631  $this->tpl->setOnScreenMessage('success', $this->lng->txt('reservation_deleted'), true);
632  $this->ctrl->redirect($this, 'log');
633  }
634 
635  protected function showRerunPreferenceAssignment(): void
636  {
637  if (!$this->checkPermissionBool('write')) {
638  return;
639  }
640  if ($this->pool->getScheduleType() === ilObjBookingPool::TYPE_NO_SCHEDULE_PREFERENCES) {
641  $pref_manager = $this->service->domain()->preferences($this->pool);
642  if ($pref_manager->hasRun()) {
643  $this->toolbar->addComponent($this->ui->factory()->button()->standard(
644  $this->lng->txt("book_rerun_assignments"),
645  $this->ctrl->getLinkTarget($this, "confirmResetRun")
646  ));
647  }
648  }
649  }
650 
651  protected function confirmResetRun()
652  {
653  if (!$this->checkPermissionBool('write')) {
654  return;
655  }
656  $this->tabs_gui->activateTab("log");
657  $mess = $this->ui->factory()->messageBox()->confirmation($this->lng->txt("book_rerun_confirmation"))->withButtons(
658  [
659  $this->ui->factory()->button()->standard(
660  $this->lng->txt("book_rerun_assignments"),
661  $this->ctrl->getLinkTarget($this, "resetRun")
662  ),
663  $this->ui->factory()->button()->standard(
664  $this->lng->txt("cancel"),
665  $this->ctrl->getLinkTarget($this, "log")
666  )
667  ]
668  );
669  $this->tpl->setContent(
670  $this->ui->renderer()->render($mess)
671  );
672  }
673 
674  protected function resetRun()
675  {
676  if (!$this->checkPermissionBool('write')) {
677  return;
678  }
679  if ($this->pool->getScheduleType() === ilObjBookingPool::TYPE_NO_SCHEDULE_PREFERENCES
680  && $this->access->checkAccess("write", "", $this->pool->getRefId())) {
681  $pref_manager = $this->service->domain()->preferences($this->pool);
682  $repo = $this->service->repo()->preferences();
683  $pref_manager->resetRun();
684  $pref_manager->storeBookings(
685  $repo->getPreferences($this->pool->getId())
686  );
687  }
688  $this->ctrl->redirect($this, "log");
689  }
690 }
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$res
Definition: ltiservices.php:69
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static changeStatus(array $a_ids, int $a_status)
Batch update reservation status.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
$type
getCmd(string $fallback_command=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
ILIAS BookingManager InternalService $service
static getObjectReservationForUser(int $a_object_id, int $a_user_id)
rsvConfirmCancel()
(C2) Confirmation screen for canceling booking from reservations screen (with and without schedule) ...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const IL_CAL_UNIX
getReservationsTable(?string $reservation_id=null)
Get reservationsTable.
getLogReservationIds()
Reservations IDs as currently provided from.
global $DIC
Definition: feed.php:28
array $details
Details for error message relating to last request processed.
Definition: System.php:109
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getNextClass($a_gui_class=null)
setContent(string $a_html)
Sets content for standard template.
rsvConfirmCancelUser()
(C1) Confirmation screen for canceling booking without schedule from booking objects screen or from p...
This class represents a number property in a property form.
static getCancelDetails(int $a_obj_id, int $a_user_id, int $a_from, int $a_to)
Get reservation ids from aggregated id for cancellation.
__construct(ilObjBookingPool $pool, ilBookingHelpAdapter $help, int $context_obj_id=0)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false)
Format a period of two dates Shows: 14.
$ilUser
Definition: imgupload.php:34
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
changeStatusObject()
Change status of given reservations.
ILIAS BookingManager StandardGUIRequest $book_request
rsvConfirmCancelAggregationForm(array $a_ids)
Form being used in (C2.a)
static lookupPoolId(int $object_id)
static setUseRelativeDates(bool $a_status)
set use relative dates
static getList(int $a_pool_id, string $a_title=null)
Get list of booking objects.
rsvCancel()
(C2.b) Cancel reservations (coming from C2 or C2.a)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
rsvConfirmCancelAggregation(array $a_ids=null)
(C2.a) Cancel aggregated booking from reservations screen (with and without schedule) called in (C2) ...