view.html.php
381 lines
| 1 | <?php |
| 2 | /** |
| 3 | * @package VikAppointments |
| 4 | * @subpackage core |
| 5 | * @author E4J s.r.l. |
| 6 | * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved. |
| 7 | * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL |
| 8 | * @link https://vikwp.com |
| 9 | */ |
| 10 | |
| 11 | // No direct access |
| 12 | defined('ABSPATH') or die('No script kiddies please!'); |
| 13 | |
| 14 | /** |
| 15 | * VikAppointments reservation management view. |
| 16 | * |
| 17 | * @since 1.0 |
| 18 | */ |
| 19 | class VikAppointmentsViewmanagereservation extends JViewVAP |
| 20 | { |
| 21 | /** |
| 22 | * Flag for multi-order layout. |
| 23 | * |
| 24 | * @var boolean |
| 25 | */ |
| 26 | public $multiOrder = false; |
| 27 | |
| 28 | /** |
| 29 | * VikAppointments view display method. |
| 30 | * |
| 31 | * @return void |
| 32 | */ |
| 33 | function display($tpl = null) |
| 34 | { |
| 35 | $app = JFactory::getApplication(); |
| 36 | $input = $app->input; |
| 37 | $dbo = JFactory::getDbo(); |
| 38 | |
| 39 | $ids = $input->getUint('cid', array()); |
| 40 | $type = $ids ? 'edit' : 'new'; |
| 41 | |
| 42 | if ($type == 'edit') |
| 43 | { |
| 44 | $q = $dbo->getQuery(true); |
| 45 | |
| 46 | // select reservation columns |
| 47 | $q->select('r.*'); |
| 48 | $q->from($dbo->qn('#__vikappointments_reservation', 'r')); |
| 49 | |
| 50 | // select employee columns |
| 51 | $q->select(array( |
| 52 | $dbo->qn('e.nickname', 'employee_name'), |
| 53 | $dbo->qn('e.timezone'), |
| 54 | $dbo->qn('e.notify'), |
| 55 | )); |
| 56 | $q->leftjoin($dbo->qn('#__vikappointments_employee', 'e') . ' ON ' . $dbo->qn('r.id_employee') . ' = ' . $dbo->qn('e.id')); |
| 57 | |
| 58 | // select service columns |
| 59 | $q->select(array( |
| 60 | $dbo->qn('s.name', 'service_name'), |
| 61 | $dbo->qn('s.duration', 'service_duration'), |
| 62 | )); |
| 63 | $q->leftjoin($dbo->qn('#__vikappointments_service', 's') . ' ON ' . $dbo->qn('r.id_service') . ' = ' . $dbo->qn('s.id')); |
| 64 | |
| 65 | // select customer columns |
| 66 | $q->select($dbo->qn('u.jid')); |
| 67 | $q->leftjoin($dbo->qn('#__vikappointments_users', 'u') . ' ON ' . $dbo->qn('r.id_user') . ' = ' . $dbo->qn('u.id')); |
| 68 | |
| 69 | // select author columns (not needed...) |
| 70 | // $q->select(array( |
| 71 | // $dbo->qn('j.name', 'author_name'), |
| 72 | // $dbo->qn('j.username', 'author_username'), |
| 73 | // )); |
| 74 | // $q->leftjoin($dbo->qn('#__users', 'j') . ' ON ' . $dbo->qn('r.createdby') . ' = ' . $dbo->qn('j.id')); |
| 75 | |
| 76 | $q->where($dbo->qn('r.id') . ' = ' . $ids[0]); |
| 77 | |
| 78 | $dbo->setQuery($q, 0, 1); |
| 79 | $reservation = $dbo->loadObject(); |
| 80 | |
| 81 | if ($reservation) |
| 82 | { |
| 83 | if ($reservation->closure == 1) |
| 84 | { |
| 85 | // edit closure from the related page |
| 86 | $app->redirect('index.php?option=com_vikappointments&task=closure.edit&cid[]=' . $reservation->id); |
| 87 | exit; |
| 88 | } |
| 89 | |
| 90 | // decode custom fields and uploads |
| 91 | $reservation->custom_f = (array) ($reservation->custom_f ? json_decode($reservation->custom_f, true) : []); |
| 92 | $reservation->attendees = (array) ($reservation->attendees ? json_decode($reservation->attendees, true) : []); |
| 93 | $reservation->uploads = (array) ($reservation->uploads ? json_decode($reservation->uploads, true) : []); |
| 94 | // merge them together |
| 95 | $reservation->custom_f = array_merge($reservation->custom_f, $reservation->uploads); |
| 96 | |
| 97 | $reservation->options = []; |
| 98 | $reservation->items = []; |
| 99 | |
| 100 | if ($reservation->id_parent == -1) |
| 101 | { |
| 102 | $this->multiOrder = true; |
| 103 | |
| 104 | // get all appointments assigned to this parent order |
| 105 | $q->clear('where'); |
| 106 | $q->clear('limit'); |
| 107 | $q->where($dbo->qn('r.id_parent') . ' = ' . $reservation->id); |
| 108 | |
| 109 | $dbo->setQuery($q); |
| 110 | $reservation->items = $dbo->loadObjectList(); |
| 111 | } |
| 112 | else |
| 113 | { |
| 114 | // load assigned options |
| 115 | $q = $dbo->getQuery(true) |
| 116 | ->select('a.*') |
| 117 | ->select($dbo->qn('o.name')) |
| 118 | ->select($dbo->qn('v.name', 'var_name')) |
| 119 | ->from($dbo->qn('#__vikappointments_option', 'o')) |
| 120 | ->leftjoin($dbo->qn('#__vikappointments_res_opt_assoc', 'a') . ' ON ' . $dbo->qn('o.id') . ' = ' . $dbo->qn('a.id_option')) |
| 121 | ->leftjoin($dbo->qn('#__vikappointments_option_value', 'v') . ' ON ' . $dbo->qn('v.id') . ' = ' . $dbo->qn('a.id_variation')) |
| 122 | ->where($dbo->qn('a.id_reservation') . ' = ' . $reservation->id) |
| 123 | ->order($dbo->qn('a.id') . ' ASC'); |
| 124 | |
| 125 | $dbo->setQuery($q); |
| 126 | $reservation->options = $dbo->loadObjectList(); |
| 127 | } |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | $this->recalculate = false; |
| 132 | |
| 133 | if (empty($reservation)) |
| 134 | { |
| 135 | $reservation = (object) $this->getBlankItem(); |
| 136 | |
| 137 | // always calculate booking data while creating new reservations |
| 138 | $this->recalculate = true; |
| 139 | } |
| 140 | else |
| 141 | { |
| 142 | // get reservation data stored within the user state |
| 143 | $tmp = $app->getUserState('vap.reservation.data', array()); |
| 144 | |
| 145 | // look for "day" attribute |
| 146 | if (isset($tmp['day'])) |
| 147 | { |
| 148 | // the user state contains "day" attribute, meaning |
| 149 | // that we are editing the details of the appointment |
| 150 | $this->recalculate = true; |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // use reservation data stored in user state |
| 155 | $this->injectUserStateData($reservation, 'vap.reservation.data'); |
| 156 | |
| 157 | if (!$this->multiOrder) |
| 158 | { |
| 159 | // get service details |
| 160 | $service = JModelVAP::getInstance('serempassoc')->getOverrides($reservation->id_service, $reservation->id_employee); |
| 161 | |
| 162 | if (!$service) |
| 163 | { |
| 164 | throw new Exception('Employee/service relation not found.', 404); |
| 165 | } |
| 166 | |
| 167 | $this->service = $service; |
| 168 | |
| 169 | if ($this->recalculate) |
| 170 | { |
| 171 | // update service name, duration and sleep time |
| 172 | $reservation->service_name = $service->name; |
| 173 | $reservation->duration = $service->duration; |
| 174 | $reservation->sleep = $service->sleep; |
| 175 | |
| 176 | // get employee details |
| 177 | $employee = JModelVAP::getInstance('employee')->getItem($reservation->id_employee); |
| 178 | |
| 179 | if (!$employee) |
| 180 | { |
| 181 | // employee not found |
| 182 | throw new Exception(sprintf('Employee [%d] not found.', $reservation->id_employee), 404); |
| 183 | } |
| 184 | |
| 185 | // update employee name, timezone and notifications flag |
| 186 | $reservation->employee_name = $employee->nickname; |
| 187 | $reservation->timezone = $employee->timezone; |
| 188 | $reservation->notify = $employee->notify; |
| 189 | |
| 190 | // recalculate reservation totals |
| 191 | $model = JModelVAP::getInstance('reservation'); |
| 192 | $model->recalculateTotals($reservation, $service); |
| 193 | } |
| 194 | |
| 195 | // replicate reservation details within the items array |
| 196 | $reservation->items = array($reservation); |
| 197 | } |
| 198 | else |
| 199 | { |
| 200 | $this->allServices = array(); |
| 201 | |
| 202 | $map = array(); |
| 203 | |
| 204 | // If multi order, we should get all the children orders |
| 205 | // to check if there is only one employee. |
| 206 | foreach ($reservation->items as $appointment) |
| 207 | { |
| 208 | // in case the employee has been already set, the last 'view_emp' will be taken |
| 209 | $map[$appointment->id_employee] = $appointment->view_emp; |
| 210 | |
| 211 | if (!in_array($appointment->id_service, $this->allServices)) |
| 212 | { |
| 213 | $this->allServices[] = $appointment->id_service; |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | $employees = array_keys($map); |
| 218 | |
| 219 | // make sure there is only one employee |
| 220 | if (count($employees) == 1) |
| 221 | { |
| 222 | // inject employee ID |
| 223 | $reservation->id_employee = $employees[0]; |
| 224 | // inject 'view_emp' |
| 225 | $reservation->view_emp = reset($map); |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | // import custom fields renderer and loader (as dependency) |
| 230 | VAPLoader::import('libraries.customfields.renderer'); |
| 231 | |
| 232 | // get relevant custom fields only |
| 233 | $fieldsLoader = VAPCustomFieldsLoader::getInstance() |
| 234 | ->translate() |
| 235 | ->noRequiredCheckbox(); |
| 236 | |
| 237 | // check whether we should include the custom fields of the employee |
| 238 | if ($reservation->view_emp && $reservation->id_employee > 0) |
| 239 | { |
| 240 | // include employee custom fields |
| 241 | $fieldsLoader->ofEmployee($reservation->id_employee); |
| 242 | } |
| 243 | |
| 244 | // check whether we should include the custom fields of the service(s) |
| 245 | if (!empty($this->allServices)) |
| 246 | { |
| 247 | // include all services assigned to the multi-order |
| 248 | $fieldsLoader->forService($this->allServices); |
| 249 | } |
| 250 | else |
| 251 | { |
| 252 | // include the custom fields of the service |
| 253 | $fieldsLoader->forService($reservation->id_service); |
| 254 | } |
| 255 | |
| 256 | // load custom fields |
| 257 | $this->customFields = $fieldsLoader->fetch(); |
| 258 | |
| 259 | // get payments |
| 260 | $payments_groups = 0; |
| 261 | |
| 262 | if (!empty($reservation->view_emp)) |
| 263 | { |
| 264 | $payments_groups = $reservation->id_employee; |
| 265 | } |
| 266 | |
| 267 | // load all the payments assigned to the selected employee |
| 268 | $this->payments = VikAppointments::getAllEmployeePayments($payments_groups); |
| 269 | |
| 270 | /** |
| 271 | * Get all unpublished and global e-mail custom texts. |
| 272 | * |
| 273 | * @since 1.6.5 |
| 274 | */ |
| 275 | $q = $dbo->getQuery(true) |
| 276 | ->select('*') |
| 277 | ->from($dbo->qn('#__vikappointments_cust_mail')) |
| 278 | ->where($dbo->qn('published') . ' = 0') |
| 279 | ->where($dbo->qn('id_employee') . ' IN (0, ' . (int) $reservation->id_employee . ')') |
| 280 | ->where($dbo->qn('id_service') . ' IN (0, ' . (int) $reservation->id_service . ')') |
| 281 | ->order($dbo->qn('id') . ' DESC'); |
| 282 | |
| 283 | $dbo->setQuery($q); |
| 284 | $templates = $dbo->loadObjectList(); |
| 285 | |
| 286 | /** |
| 287 | * Load all notes assigned to this reservation. |
| 288 | * |
| 289 | * @since 1.7 |
| 290 | */ |
| 291 | $q = $dbo->getQuery(true) |
| 292 | ->select('*') |
| 293 | ->from($dbo->qn('#__vikappointments_user_notes')) |
| 294 | ->where($dbo->qn('id_parent') . ' = ' . (int) $reservation->id) |
| 295 | ->where($dbo->qn('group') . ' = ' . $dbo->q('appointments')) |
| 296 | ->order(sprintf( |
| 297 | 'IFNULL(%s, %s) %s', |
| 298 | $dbo->qn('modifiedon'), |
| 299 | $dbo->qn('createdon'), |
| 300 | 'DESC' |
| 301 | )); |
| 302 | |
| 303 | $dbo->setQuery($q); |
| 304 | $this->usernotes = $dbo->loadObjectList(); |
| 305 | |
| 306 | $this->reservation = $reservation; |
| 307 | $this->mailTemplates = $templates; |
| 308 | $this->from = $input->get('from'); |
| 309 | |
| 310 | // set the toolbar |
| 311 | $this->addToolBar($type); |
| 312 | |
| 313 | // display the template |
| 314 | parent::display($tpl); |
| 315 | } |
| 316 | |
| 317 | /** |
| 318 | * Returns a blank item. |
| 319 | * |
| 320 | * @return array A blank item for new requests. |
| 321 | */ |
| 322 | protected function getBlankItem() |
| 323 | { |
| 324 | // get blank item |
| 325 | $item = JModelVAP::getInstance('reservation')->getItem(0, $blank = true); |
| 326 | |
| 327 | $item->custom_f = array(); |
| 328 | $item->attendees = array(); |
| 329 | $item->options = array(); |
| 330 | $item->jid = 0; |
| 331 | |
| 332 | return $item; |
| 333 | } |
| 334 | |
| 335 | /** |
| 336 | * Setting the toolbar. |
| 337 | * |
| 338 | * @return void |
| 339 | */ |
| 340 | protected function addToolBar($type) |
| 341 | { |
| 342 | // add menu title and some buttons to the page |
| 343 | if ($type == 'edit') |
| 344 | { |
| 345 | JToolBarHelper::title(JText::translate('VAPMAINTITLEEDITRESERVATION'), 'vikappointments'); |
| 346 | } |
| 347 | else |
| 348 | { |
| 349 | JToolBarHelper::title(JText::translate('VAPMAINTITLENEWRESERVATION'), 'vikappointments'); |
| 350 | } |
| 351 | |
| 352 | $user = JFactory::getUser(); |
| 353 | |
| 354 | if ($user->authorise('core.edit', 'com_vikappointments') |
| 355 | || $user->authorise('core.create', 'com_vikappointments')) |
| 356 | { |
| 357 | if (!$this->multiOrder) |
| 358 | { |
| 359 | JToolbarHelper::apply('reservation.save', JText::translate('VAPSAVE')); |
| 360 | JToolbarHelper::save('reservation.saveclose', JText::translate('VAPSAVEANDCLOSE')); |
| 361 | } |
| 362 | else |
| 363 | { |
| 364 | JToolbarHelper::apply('multiorder.save', JText::translate('VAPSAVE')); |
| 365 | JToolbarHelper::save('multiorder.saveclose', JText::translate('VAPSAVEANDCLOSE')); |
| 366 | } |
| 367 | } |
| 368 | |
| 369 | if ($user->authorise('core.edit', 'com_vikappointments') |
| 370 | && $user->authorise('core.create', 'com_vikappointments')) |
| 371 | { |
| 372 | if (!$this->multiOrder) |
| 373 | { |
| 374 | JToolbarHelper::save2new('reservation.savenew', JText::translate('VAPSAVEANDNEW')); |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | JToolBarHelper::cancel('reservation.cancel', $type == 'edit' ? 'JTOOLBAR_CLOSE' : 'JTOOLBAR_CANCEL'); |
| 379 | } |
| 380 | } |
| 381 |