PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / trunk
VikAppointments Services Booking Calendar vtrunk
trunk 1.2.17 1.2.18 1.2.19
vikappointments / admin / models / subscrorder.php
vikappointments / admin / models Last commit date
apiban.php 4 years ago apilog.php 2 years ago apiplugin.php 4 years ago apiuser.php 2 years ago apiuseroptions.php 2 years ago backup.php 5 months ago caldays.php 1 month ago calendar.php 1 month ago city.php 4 years ago closure.php 1 month ago configapp.php 4 years ago configcldays.php 4 years ago configcron.php 4 years ago configemp.php 4 years ago configsmsapi.php 4 years ago configuration.php 5 months ago conversion.php 4 years ago country.php 2 years ago coupon.php 2 years ago couponemployee.php 4 years ago coupongroup.php 2 years ago couponservice.php 4 years ago cronjob.php 2 years ago cronjoblog.php 4 years ago customer.php 5 months ago customf.php 2 years ago customfservice.php 4 years ago customizer.php 4 years ago empgroup.php 2 years ago employee.php 2 years ago empsettings.php 4 years ago file.php 4 years ago findreservation.php 1 month ago group.php 2 years ago import.php 4 years ago index.html 4 years ago invoice.php 1 month ago langcustomf.php 4 years ago langempgroup.php 4 years ago langemployee.php 4 years ago langgroup.php 4 years ago langmedia.php 4 years ago langoption.php 2 years ago langoptiongroup.php 4 years ago langoptionvar.php 4 years ago langpackage.php 4 years ago langpackgroup.php 4 years ago langpayment.php 4 years ago langservice.php 4 years ago langstatuscode.php 4 years ago langsubscr.php 4 years ago langtax.php 2 years ago langtaxrule.php 4 years ago location.php 2 years ago mailtext.php 2 years ago makerecurrence.php 1 month ago media.php 2 years ago multiorder.php 1 month ago option.php 1 year ago optiongroup.php 2 years ago optionvar.php 1 year ago orderstatus.php 2 years ago package.php 2 years ago packageservice.php 4 years ago packgroup.php 2 years ago packorder.php 2 years ago packorderitem.php 1 month ago payment.php 2 years ago rate.php 2 years ago reportsemp.php 5 months ago reportsser.php 5 months ago reservation.php 1 month ago resoptassoc.php 2 years ago restriction.php 2 years ago review.php 3 years ago serempassoc.php 1 year ago seroptassoc.php 4 years ago serrateassoc.php 4 years ago serrestrassoc.php 4 years ago service.php 2 years ago state.php 2 years ago statswidget.php 2 years ago statuscode.php 2 years ago subscription.php 1 month ago subscrorder.php 1 month ago tag.php 4 years ago tax.php 2 years ago taxrule.php 2 years ago updateprogram.php 4 years ago usernote.php 2 years ago waitinglist.php 1 month ago webhook.php 1 year ago worktime.php 1 month ago
subscrorder.php
538 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 VAPLoader::import('libraries.mvc.model');
15
16 /**
17 * VikAppointments subscription order model.
18 *
19 * @since 1.7
20 */
21 class VikAppointmentsModelSubscrorder extends JModelVAP
22 {
23 /**
24 * Basic save implementation.
25 *
26 * @param mixed $data Either an array or an object of data to save.
27 *
28 * @return mixed The ID of the record on success, false otherwise.
29 */
30 public function save($data)
31 {
32 $data = (array) $data;
33
34 $new_is_approved = $old_is_approved = false;
35
36 if (!empty($data['status']))
37 {
38 // check whether the specified status is an approval
39 $new_is_approved = JHtml::fetch('vaphtml.status.isapproved', 'subscriptions', $data['status']);
40
41 if (!empty($data['id']))
42 {
43 // we are doing an update, retrieve previous order status
44 $table = $this->getTable();
45 $table->load($data['id']);
46
47 // check whether the previous status was an approval too
48 $old_is_approved = JHtml::fetch('vaphtml.status.isapproved', 'subscriptions', $table->status);
49
50 if (!isset($data['id_employee']))
51 {
52 // register previous employee ID, needed to extend a license
53 $data['id_employee'] = $table->id_employee;
54 }
55
56 if (!isset($data['id_user']))
57 {
58 // register previous user ID, needed to extend a license
59 $data['id_user'] = $table->id_user;
60 }
61
62 if (!isset($data['id_subscr']))
63 {
64 // register previous subscription ID, needed to extend a license
65 $data['id_subscr'] = $table->id_subscr;
66 }
67 }
68 }
69
70 if (!isset($data['payment_charge']) && isset($data['id_payment']))
71 {
72 if ($data['id_payment'] > 0)
73 {
74 // missing payment charge, get payment table
75 $payTable = JModelVAP::getInstance('payment')->getTable();
76
77 // attempt to load the payment details
78 if ($payTable->load($data['id_payment']))
79 {
80 $data['payment_charge'] = (float) $payTable->charge;
81 }
82 }
83 else
84 {
85 // empty payment, unset charge
86 $data['payment_charge'] = 0;
87 }
88 }
89
90 // attempt to save the record
91 $id = parent::save($data);
92
93 if (!$id)
94 {
95 // something went wrong
96 return false;
97 }
98
99 // always clear order from cache after saving
100 VAPLoader::import('libraries.order.factory');
101 VAPOrderFactory::changed('subscr', $id);
102 VAPOrderFactory::changed('empsubscr', $id);
103
104 // extend subscription only in case the new status is an approval
105 // and the previous one wasn't
106 if ($new_is_approved && !$old_is_approved && !empty($data['id_subscr']))
107 {
108 if (!empty($data['id_user']))
109 {
110 // extend customer license by the subscription
111 $this->extendCustomer($data['id_user'], $data['id_subscr']);
112 }
113 else if (!empty($data['id_employee']))
114 {
115 // extend employee license by the subscription
116 $this->extendEmployee($data['id_employee'], $data['id_subscr']);
117 }
118 }
119
120 // check whether we should apply or delete a discount
121 if (!empty($data['add_discount']))
122 {
123 $this->addDiscount($id, $data['add_discount']);
124 }
125 else if (!empty($data['remove_discount']))
126 {
127 $this->removeDiscount($id);
128 }
129
130 return $id;
131 }
132
133 /**
134 * Extends the expiration date of the specified customer by
135 * the duration of the given subscription.
136 *
137 * @param mixed $customer Either a customer object or its ID.
138 * @param mixed $subscription Either a subscription object or its ID.
139 * @param boolean $message True to enqueue a message, false to ignore it.
140 *
141 * @return mixed The resulting date on success, false otherwise.
142 */
143 public function extendCustomer($customer, $subscription, $message = true)
144 {
145 // get customer model for later use
146 $customerModel = JModelVAP::getInstance('customer');
147
148 // check if we have an ID
149 if (is_numeric($customer))
150 {
151 // get customer details
152 $customer = $customerModel->getItem((int) $customer);
153
154 if (!$customer)
155 {
156 // customer not found
157 return false;
158 }
159 }
160
161 // always cast to object
162 $customer = (object) $customer;
163
164 if ($customer->lifetime)
165 {
166 // the customer owns a lifetime subscription,
167 // we don't need to update its expiration
168 return false;
169 }
170
171 $to = 0;
172 $str = "";
173
174 // get current time
175 $now = JFactory::getDate()->toSql();
176
177 if (VAPDateHelper::isNull($customer->active_to_date) || $customer->active_to_date < $now)
178 {
179 // the customer was pending or expired, renew from now on
180 $customer->active_to_date = $now;
181 }
182
183 // get subscription model
184 $subscrModel = JModelVAP::getInstance('subscription');
185
186 // extend date by the duration of the given subscription
187 $customer->active_to_date = $subscrModel->extend($customer->active_to_date, $subscription);
188
189 if ($customer->active_to_date === false)
190 {
191 // something went wrong...
192 return false;
193 }
194
195 // prepare data to save
196 $data = array(
197 'id' => $customer->id,
198 'lifetime' => $customer->active_to_date == -1 ? 1 : 0,
199 'active_to_date' => $customer->active_to_date == -1 ? null : $customer->active_to_date,
200 );
201
202 if (VAPDateHelper::isNull($customer->active_since))
203 {
204 // register first activation date
205 $data['active_since'] = $now;
206 }
207
208 // update customer record
209 $customerModel->save($data);
210
211 // check if we should enqueue a successful message
212 if ($message)
213 {
214 $app = JFactory::getApplication();
215
216 if ($data['lifetime'])
217 {
218 /**
219 * Get LIFETIME text based on the current application client.
220 *
221 * @since 1.6.1
222 */
223 if ($app->isClient('site'))
224 {
225 $str = JText::translate('VAPACCOUNTVALIDTHRU1');
226 }
227 else
228 {
229 $str = JText::translate('VAPSUBSCRTYPE5');
230 }
231 }
232 else
233 {
234 $config = VAPFactory::getConfig();
235
236 // format expiration date
237 $str = JHtml::fetch('date', $customer->active_to_date, JText::translate('DATE_FORMAT_LC3') . ' ' . $config->get('timeformat'));
238 }
239
240 /**
241 * Display the message based on the current application client.
242 *
243 * @since 1.6.1
244 */
245 if ($app->isClient('site'))
246 {
247 $str = JText::sprintf('VAPSUBSCRIPTIONEXTENDED_SITE', $str);
248 }
249 else
250 {
251 $str = JText::sprintf('VAPSUBSCRIPTIONEXTENDED', $customer->billing_name, $str);
252 }
253
254 // enqueue message
255 $app->enqueueMessage($str);
256 }
257
258 return $customer->active_to_date;
259 }
260
261 /**
262 * Extends the expiration date of the specified employee by
263 * the duration of the given subscription.
264 *
265 * @param mixed $employee Either an employee object or its ID.
266 * @param mixed $subscription Either a subscription object or its ID.
267 * @param boolean $message True to enqueue a message, false to ignore it.
268 *
269 * @return mixed The resulting date on success, false otherwise.
270 */
271 public function extendEmployee($employee, $subscription, $message = true)
272 {
273 // get employee model for later use
274 $employeeModel = JModelVAP::getInstance('employee');
275
276 // check if we have an ID
277 if (is_numeric($employee))
278 {
279 // get employee details
280 $employee = $employeeModel->getItem($employee);
281
282 if (!$employee)
283 {
284 // employee not found
285 return false;
286 }
287 }
288
289 // always cast to object
290 $employee = (object) $employee;
291
292 if ($employee->active_to == -1)
293 {
294 // the employee owns a lifetime subscription,
295 // we don't need to update its expiration
296 return false;
297 }
298
299 $to = 0;
300 $str = "";
301
302 // get current time
303 $now = JFactory::getDate()->toSql();
304
305 if ($employee->active_to == 0 || $employee->active_to_date < $now)
306 {
307 // the employee was pending or expired, renew from now on
308 $employee->active_to_date = $now;
309 }
310
311 // get subscription model
312 $subscrModel = JModelVAP::getInstance('subscription');
313
314 // extend date by the duration of the given subscription
315 $employee->active_to_date = $subscrModel->extend($employee->active_to_date, $subscription);
316
317 if ($employee->active_to_date === false)
318 {
319 // something went wrong...
320 return false;
321 }
322
323 // prepare data to save
324 $data = array(
325 'id' => $employee->id,
326 'active_to' => $employee->active_to_date == -1 ? -1 : 1,
327 'active_to_date' => $employee->active_to_date,
328 'listable' => 1,
329 );
330
331 if (VAPDateHelper::isNull($employee->active_since))
332 {
333 // register first activation date
334 $data['active_since'] = $now;
335 }
336
337 // update employee record
338 $employeeModel->save($data);
339
340 // check if we should enqueue a successful message
341 if ($message)
342 {
343 $app = JFactory::getApplication();
344
345 if ($employee->active_to_date == -1)
346 {
347 /**
348 * Get LIFETIME text based on the current application client.
349 *
350 * @since 1.6.1
351 */
352 if ($app->isClient('site'))
353 {
354 $str = JText::translate('VAPACCOUNTVALIDTHRU1');
355 }
356 else
357 {
358 $str = JText::translate('VAPSUBSCRTYPE5');
359 }
360 }
361 else
362 {
363 $config = VAPFactory::getConfig();
364
365 // format expiration date
366 $str = JHtml::fetch('date', $employee->active_to_date, JText::translate('DATE_FORMAT_LC3') . ' ' . $config->get('timeformat'));
367 }
368
369 /**
370 * Display the message based on the current application client.
371 *
372 * @since 1.6.1
373 */
374 if ($app->isClient('site'))
375 {
376 $str = JText::sprintf('VAPSUBSCRIPTIONEXTENDED_SITE', $str);
377 }
378 else
379 {
380 $str = JText::sprintf('VAPSUBSCRIPTIONEXTENDED', $employee->nickname, $str);
381 }
382
383 // enqueue message
384 $app->enqueueMessage($str);
385 }
386
387 return $employee->active_to_date;
388 }
389
390 /**
391 * Adds a discount to the specified subscription order.
392 *
393 * @param integer $id The order ID.
394 * @param mixed $coupon Either a coupon code or an array/object
395 * containing its details.
396 *
397 * @return boolean True on success, false otherwise.
398 */
399 public function addDiscount($id, $coupon)
400 {
401 // get coupon model
402 $couponModel = JModelVAP::getInstance('coupon');
403
404 if (is_string($coupon))
405 {
406 // get coupon code details
407 $coupon = $couponModel->getCoupon($coupon);
408 }
409 else
410 {
411 // treat as object
412 $coupon = (object) $coupon;
413 }
414
415 // make sure we have a valid coupon code
416 if (!$coupon || empty($coupon->value))
417 {
418 // invalid/missing coupon
419 $this->setError('Missing coupon code');
420
421 return false;
422 }
423
424 // load subscription order details
425 $table = $this->getTable();
426 $table->load((int) $id);
427
428 // get subscription cost
429 $subTable = JModelVAP::getInstance('subscription')->getTable();
430 $subTable->load($table->id_subscr);
431
432 // define options for tax calculation
433 $options = array(
434 'subject' => 'subscription',
435 'id_employee' => $table->id_employee,
436 );
437
438 // prepare order data
439 $orderData = array(
440 'id' => $table->id,
441 'total_cost' => $table->payment_charge + $table->payment_tax,
442 'total_net' => 0,
443 'total_tax' => $table->payment_tax,
444 'discount' => 0,
445 'coupon' => '',
446 );
447
448 VAPLoader::import('libraries.tax.factory');
449
450 if (empty($coupon->percentot) || $coupon->percentot == 1)
451 {
452 // percentage discount
453 $orderData['discount'] = round($subTable->price * $coupon->value / 100, 2);
454 }
455 else
456 {
457 // fixed discount
458 $orderData['discount'] = $coupon->value;
459 }
460
461 // recalculate totals
462 $totals = VAPTaxFactory::calculate($table->id_subscr, $subTable->price - $orderData['discount'], $options);
463
464 // update order totals
465 $orderData['total_net'] += $totals->net;
466 $orderData['total_tax'] += $totals->tax;
467 $orderData['total_cost'] += $totals->gross;
468
469 if (!empty($coupon->code))
470 {
471 // save coupon data
472 $orderData['coupon'] = $coupon;
473
474 // redeem coupon usage
475 $couponModel->redeem($coupon);
476 }
477
478 // update order details
479 return $this->save($orderData);
480 }
481
482 /**
483 * Removes discount from the specified subscription order.
484 *
485 * @param integer $id The order ID.
486 *
487 * @return boolean True on success, false otherwise.
488 */
489 public function removeDiscount($id)
490 {
491 // load subscription order details
492 $table = $this->getTable();
493 $table->load((int) $id);
494
495 if ($table->coupon)
496 {
497 // decode coupon string
498 $coupon = explode(';;', $table->coupon);
499
500 // unredeem coupon usage
501 JModelVAP::getInstance('coupon')->unredeem($coupon[0]);
502 }
503
504 // get subscription cost
505 $subTable = JModelVAP::getInstance('subscription')->getTable();
506 $subTable->load($table->id_subscr);
507
508 // define options for tax calculation
509 $options = array(
510 'subject' => 'subscription',
511 'id_employee' => $table->id_employee,
512 );
513
514 // prepare order data
515 $orderData = array(
516 'id' => $table->id,
517 'total_cost' => $table->payment_charge + $table->payment_tax,
518 'total_net' => 0,
519 'total_tax' => $table->payment_tax,
520 'discount' => 0,
521 'coupon' => '',
522 );
523
524 VAPLoader::import('libraries.tax.factory');
525
526 // recalculate totals
527 $totals = VAPTaxFactory::calculate($table->id_subscr, $subTable->price, $options);
528
529 // update order totals
530 $orderData['total_net'] += $totals->net;
531 $orderData['total_tax'] += $totals->tax;
532 $orderData['total_cost'] += $totals->gross;
533
534 // update order details
535 return $this->save($orderData);
536 }
537 }
538