PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / trunk
VikAppointments Services Booking Calendar vtrunk
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / site / views / order / view.html.php
vikappointments / site / views / order Last commit date
tmpl 3 months ago index.html 7 years ago view.html.php 6 months ago
view.html.php
428 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 (order) summary view.
16 * In case the request doesn't provide the ORDER NUMBER
17 * and the ORDER KEY, a form to search a reservation
18 * will be displayed.
19 *
20 * @since 1.0
21 */
22 class VikAppointmentsVieworder extends JViewVAP
23 {
24 /**
25 * VikAppointments view display method.
26 *
27 * @return void
28 */
29 function display($tpl = null)
30 {
31 $app = JFactory::getApplication();
32 $input = $app->input;
33 $config = VAPFactory::getConfig();
34
35 $oid = $input->get('ordnum', 0, 'uint');
36 $sid = $input->get('ordkey', '', 'alnum');
37
38 $this->itemid = $input->getInt('Itemid', 0);
39
40 $order = null;
41
42 if (!empty($oid) && !empty($sid))
43 {
44 // check whether the appointment has expired
45 JModelVAP::getInstance('reservation')->checkExpired(array('id' => $oid));
46
47 try
48 {
49 // get order details (filter by ID and SID)
50 VAPLoader::import('libraries.order.factory');
51 $order = VAPOrderFactory::getAppointments($oid, JFactory::getLanguage()->getTag(), array('sid' => $sid));
52 }
53 catch (Exception $e)
54 {
55 // reservation not found
56 }
57
58 if ($order)
59 {
60 // check if a payment is required
61 if ($order->payment)
62 {
63 // reload payment details to access the parameters
64 $payment = JModelVAP::getInstance('payment')->getItem($order->payment->id);
65
66 // apply payment translations
67 $payment->name = $order->payment->name;
68 $payment->prenote = $order->payment->notes->beforePurchase;
69 $payment->note = $order->payment->notes->afterPurchase;
70
71 $paymentData = array();
72
73 $vik = VAPApplication::getInstance();
74
75 /**
76 * The payment URLs are correctly routed for external usage.
77 *
78 * @since 1.6
79 */
80 $return_url = $vik->routeForExternalUse("index.php?option=com_vikappointments&view=order&ordnum={$oid}&ordkey={$sid}", false);
81 $error_url = $vik->routeForExternalUse("index.php?option=com_vikappointments&view=order&ordnum={$oid}&ordkey={$sid}", false);
82
83 /**
84 * Include the Notification URL in both the PLAIN and ROUTED formats.
85 *
86 * @since 1.7
87 */
88 $notify_url = "index.php?option=com_vikappointments&task=order.notifypayment&ordnum={$oid}&ordkey={$sid}";
89
90 if ($order->statusRole == 'PENDING')
91 {
92 // check if the customer should pay the full amount (only for PENDING orders)
93 $this->shouldPayFullAmount($order);
94 }
95
96 /**
97 * Calculate the total amount to pay.
98 *
99 * @since 1.7.8
100 */
101 $total_to_pay = VikAppointments::getTotalBeforePayment($order);
102
103 $paymentData['type'] = 'appointments';
104 $paymentData['action'] = 'create';
105 $paymentData['oid'] = $order->id;
106 $paymentData['sid'] = $order->sid;
107 $paymentData['attempt'] = $order->payment_attempt;
108 $paymentData['transaction_name'] = JText::sprintf('VAPTRANSACTIONNAME', $config->get('agencyname'));
109 $paymentData['transaction_currency'] = $config->get('currencyname');
110 $paymentData['currency_symb'] = $config->get('currencysymb');
111 $paymentData['tax'] = 0;
112 $paymentData['return_url'] = $return_url;
113 $paymentData['error_url'] = $error_url;
114 $paymentData['notify_url'] = $vik->routeForExternalUse($notify_url, false);
115 $paymentData['notify_url_plain'] = JUri::root() . $notify_url;
116 $paymentData['total_to_pay'] = $total_to_pay;
117 $paymentData['total_net_price'] = $total_to_pay;
118 $paymentData['total_tax'] = 0;
119 $paymentData['leavedeposit'] = false; // @deprecated
120 $paymentData['payfull'] = true; // @deprecated
121 $paymentData['payment_info'] = $payment;
122 $paymentData['details'] = array(
123 'purchaser_nominative' => $order->purchaser_nominative,
124 'purchaser_mail' => $order->purchaser_mail,
125 'purchaser_phone' => $order->purchaser_phone,
126 );
127
128 /**
129 * Added support for customer billing details.
130 *
131 * @since 1.7
132 */
133 $paymentData['billing'] = $order->billing;
134
135 /**
136 * Trigger event to manipulate the payment details.
137 *
138 * @param array &$order The transaction details.
139 * @param mixed &$params The payment configuration as array or JSON.
140 *
141 * @return void
142 *
143 * @since 1.6
144 */
145 VAPFactory::getEventDispatcher()->trigger('onInitPaymentTransaction', array(&$paymentData, &$paymentData['payment_info']->params));
146
147 // register the payment details
148 $this->payment = $paymentData;
149 }
150
151 // register all the locations
152 $this->locations = array();
153
154 foreach ($order->appointments as $appointment)
155 {
156 if ($appointment->location)
157 {
158 // create location marker
159 $marker = new stdClass;
160 $marker->lat = $appointment->location->latitude;
161 $marker->lng = $appointment->location->longitude;
162
163 // check whether the same marker was already in the list
164 for ($i = 0, $found = false; $i < count($this->locations) && !$found; $i++)
165 {
166 $found = (
167 $this->locations[$i]->lat === $marker->lat
168 && $this->locations[$i]->lng === $marker->lng
169 );
170 }
171
172 /**
173 * Exclude the locations that have not specified the coordinates,
174 * since it wouldn't be possible to display them through Google Maps.
175 *
176 * @since 1.7.1
177 */
178 if (!$found && $marker->lat !== null && $marker->lng !== null)
179 {
180 // create marker label built as [SERVICE], [EMPLOYEE] (optional) <br /> [CHECK-IN]
181 $marker->label = $appointment->service->name;
182
183 if ($appointment->viewEmp)
184 {
185 $marker->label .= ', ' . $appointment->employee->name;
186 }
187
188 $marker->label .= '<br />' . $appointment->customerCheckin->lc2;
189
190 // register full location address
191 $marker->address = $appointment->location->text;
192
193 // marker not found, add it in the list
194 $this->locations[] = $marker;
195 }
196 }
197 }
198
199 // sort order appointments by service check-in
200 $this->services = $this->sortOrdersByServiceDate($order);
201 }
202 else
203 {
204 // raise error, reservation not found
205 $app->enqueueMessage(JText::translate('VAPORDERRESERVATIONERROR'), 'error');
206 }
207 }
208
209 if (!$order)
210 {
211 // use "track" layout in case the order
212 // was not found or in case the order number
213 // and the order key was not submitted
214 $this->setLayout('track');
215 }
216 else
217 {
218 // print conversion code if needed
219 VAPLoader::import('libraries.models.conversion');
220 VAPConversion::getInstance(array('page' => 'order'))->trackCode($order);
221
222 // register order details on success
223 $this->order = $order;
224
225 // count the number of confirmed appointments
226 $this->canUserCancelAll = true;
227
228 $services_id = [];
229
230 foreach ($order->appointments as $appointment)
231 {
232 // check whether the user can cancel this appointment
233 $appointment->canUserCancel = VikAppointments::canUserCancelOrder($appointment);
234 // update global flag
235 $this->canUserCancelAll = $this->canUserCancelAll && $appointment->canUserCancel;
236
237 $services_id[] = $appointment->service->id;
238 }
239
240 /**
241 * Fetch the custom fields that the user can update, if any.
242 *
243 * @since 1.7.7
244 */
245 $this->editableFields = VikAppointments::getEditableOrderFields($order)->fetch();
246 }
247
248 // prepare page content
249 VikAppointments::prepareContent($this);
250
251 // extend pathway for breadcrumbs module
252 $this->extendPathway($app);
253
254 // Display the template
255 parent::display($tpl);
256 }
257
258 /**
259 * Sort the appointments by service ID and then by check-in date.
260 *
261 * @param VAPOrderAppointment $order The appointment details object.
262 *
263 * @return array An array containing the grouped services.
264 *
265 * @since 1.4
266 */
267 protected function sortOrdersByServiceDate($order)
268 {
269 $list = $order->appointments;
270
271 usort($list, function($a, $b)
272 {
273 // get ordering factor based on service ID
274 $factor = $a->service->id - $b->service->id;
275
276 if ($factor == 0)
277 {
278 // same service ID, get ordering factor based on check-in
279 $factor = $a->checkin->timestamp - $b->checkin->timestamp;
280 }
281
282 return $factor;
283 });
284
285 $map = array();
286
287 // group appointments by service
288 foreach ($list as $app)
289 {
290 if (!isset($map[$app->service->id]))
291 {
292 $map[$app->service->id] = array();
293 }
294
295 $map[$app->service->id][] = $app;
296 }
297
298 return $map;
299 }
300
301 /**
302 * Checks whether the specified user is allowed to pay the full amount
303 * in place of the requested deposit.
304 *
305 * @param VAPOrderAppointment $order The appointment details object.
306 *
307 * @return boolean True in case the full amount should be paid, false
308 * otherwise (or in case the deposit is disabled).
309 *
310 * @since 1.6
311 */
312 protected function shouldPayFullAmount($order)
313 {
314 if (VAPFactory::getConfig()->getUint('usedeposit') != 1)
315 {
316 // deposit is disabled or doesn't allow the users to pay the full amount
317 return false;
318 }
319
320 // value set after checking the input to pay the full amount instead than the deposit
321 $pay_full_amount = JFactory::getApplication()->input->getUint('payfull', null);
322
323 if (!is_null($pay_full_amount))
324 {
325 // update order details with given decision
326 $order->skip_deposit = $pay_full_amount;
327
328 $dbo = JFactory::getDbo();
329
330 // commit in database too
331 $q = $dbo->getQuery(true)
332 ->update($dbo->qn('#__vikappointments_reservation'))
333 ->set($dbo->qn('skip_deposit') . ' = ' . $pay_full_amount)
334 ->where(array(
335 $dbo->qn('id') . ' = ' . $order->id,
336 $dbo->qn('id_parent') . ' = ' . $order->id_parent,
337 ), 'OR');
338
339 $dbo->setQuery($q);
340 $dbo->execute();
341 }
342
343 return (bool) $order->skip_deposit;
344 }
345
346 /**
347 * Checks whether the payment (if needed) matches the specified position.
348 * In that case, the payment form/notes will be echoed.
349 *
350 * @param string $position The position in which to print the payment.
351 *
352 * @return string The HTML to display.
353 *
354 * @since 1.7
355 */
356 protected function displayPayment($position)
357 {
358 if (empty($this->payment))
359 {
360 // nothing to display
361 return '';
362 }
363
364 $position = 'vap-payment-position-' . $position;
365
366 // get payment position
367 $tmp = $this->payment['payment_info']->position;
368
369 if (!$tmp)
370 {
371 // use bottom-left by default
372 $tmp = 'vap-payment-position-bottom-left';
373 }
374
375 // compare payment position
376 if (strpos($tmp, $position) === false)
377 {
378 // position doesn't match
379 return '';
380 }
381
382 // build display data
383 $data = array(
384 'data' => $this->payment,
385 'order' => $this->order,
386 'scope' => 'appointments',
387 );
388
389 // get status role to identify the correct payment layout
390 $status = strtolower($this->order->statusRole);
391
392 if (!$status)
393 {
394 // unable to detect the status role...
395 return '';
396 }
397
398 // return payment layout based on current status role
399 return JLayoutHelper::render('blocks.payment.' . $status, $data);
400 }
401
402 /**
403 * Extends the pathway for breadcrumbs module.
404 *
405 * @param mixed $app The application instance.
406 *
407 * @return void
408 *
409 * @since 1.7
410 */
411 protected function extendPathway($app)
412 {
413 $pathway = $app->getPathway();
414 $items = $pathway->getPathway();
415 $last = end($items);
416
417 // Make sure the order page is not a menu item, otherwise
418 // the pathway will display something like:
419 // Home > Menu > Order > [ORDNUM]-[ORDKEY]
420 if ($last && strpos($last->link, '&view=order') === false && !empty($this->order))
421 {
422 // register link into the Breadcrumb
423 $link = 'index.php?option=com_vikappointments&view=order&ordnum=' . $this->order->id . '&ordkey=' . $this->order->sid;
424 $pathway->addItem($this->order->id . '-' . $this->order->sid, $link);
425 }
426 }
427 }
428