1 | <?php |
||
2 | /* For license terms, see /license.txt */ |
||
3 | |||
4 | use Chamilo\CoreBundle\Entity\Course; |
||
5 | use Chamilo\CoreBundle\Entity\Session; |
||
6 | use Doctrine\ORM\Query\Expr\Join; |
||
7 | use Symfony\Component\HttpFoundation\Request as HttpRequest; |
||
8 | |||
9 | /** |
||
10 | * Plugin class for the BuyCourses plugin. |
||
11 | * |
||
12 | * @package chamilo.plugin.buycourses |
||
13 | * |
||
14 | * @author Jose Angel Ruiz <[email protected]> |
||
15 | * @author Imanol Losada <[email protected]> |
||
16 | * @author Alex Aragón <[email protected]> |
||
17 | * @author Angel Fernando Quiroz Campos <[email protected]> |
||
18 | * @author José Loguercio Silva <[email protected]> |
||
19 | * @author Julio Montoya |
||
20 | */ |
||
21 | class BuyCoursesPlugin extends Plugin |
||
22 | { |
||
23 | public const TABLE_PAYPAL = 'plugin_buycourses_paypal_account'; |
||
24 | public const TABLE_CURRENCY = 'plugin_buycourses_currency'; |
||
25 | public const TABLE_ITEM = 'plugin_buycourses_item'; |
||
26 | public const TABLE_ITEM_BENEFICIARY = 'plugin_buycourses_item_rel_beneficiary'; |
||
27 | public const TABLE_SALE = 'plugin_buycourses_sale'; |
||
28 | public const TABLE_TRANSFER = 'plugin_buycourses_transfer'; |
||
29 | public const TABLE_COMMISSION = 'plugin_buycourses_commission'; |
||
30 | public const TABLE_PAYPAL_PAYOUTS = 'plugin_buycourses_paypal_payouts'; |
||
31 | public const TABLE_SERVICES = 'plugin_buycourses_services'; |
||
32 | public const TABLE_SERVICES_SALE = 'plugin_buycourses_service_sale'; |
||
33 | public const TABLE_CULQI = 'plugin_buycourses_culqi'; |
||
34 | public const TABLE_GLOBAL_CONFIG = 'plugin_buycourses_global_config'; |
||
35 | public const TABLE_INVOICE = 'plugin_buycourses_invoices'; |
||
36 | public const TABLE_TPV_REDSYS = 'plugin_buycourses_tpvredsys_account'; |
||
37 | public const TABLE_COUPON = 'plugin_buycourses_coupon'; |
||
38 | public const TABLE_COUPON_ITEM = 'plugin_buycourses_coupon_rel_item'; |
||
39 | public const TABLE_COUPON_SERVICE = 'plugin_buycourses_coupon_rel_service'; |
||
40 | public const TABLE_SUBSCRIPTION = 'plugin_buycourses_subscription'; |
||
41 | public const TABLE_SUBSCRIPTION_SALE = 'plugin_buycourses_subscription_rel_sale'; |
||
42 | public const TABLE_SUBSCRIPTION_PERIOD = 'plugin_buycourses_subscription_period'; |
||
43 | public const TABLE_COUPON_SALE = 'plugin_buycourses_coupon_rel_sale'; |
||
44 | public const TABLE_COUPON_SERVICE_SALE = 'plugin_buycourses_coupon_rel_service_sale'; |
||
45 | public const TABLE_COUPON_SUBSCRIPTION_SALE = 'plugin_buycourses_coupon_rel_subscription_sale'; |
||
46 | public const TABLE_STRIPE = 'plugin_buycourses_stripe_account'; |
||
47 | public const TABLE_TPV_CECABANK = 'plugin_buycourses_cecabank_account'; |
||
48 | public const PRODUCT_TYPE_COURSE = 1; |
||
49 | public const PRODUCT_TYPE_SESSION = 2; |
||
50 | public const PRODUCT_TYPE_SERVICE = 3; |
||
51 | public const PAYMENT_TYPE_PAYPAL = 1; |
||
52 | public const PAYMENT_TYPE_TRANSFER = 2; |
||
53 | public const PAYMENT_TYPE_CULQI = 3; |
||
54 | public const PAYMENT_TYPE_TPV_REDSYS = 4; |
||
55 | public const PAYMENT_TYPE_STRIPE = 5; |
||
56 | public const PAYMENT_TYPE_TPV_CECABANK = 6; |
||
57 | public const PAYOUT_STATUS_CANCELED = 2; |
||
58 | public const PAYOUT_STATUS_PENDING = 0; |
||
59 | public const PAYOUT_STATUS_COMPLETED = 1; |
||
60 | public const SALE_STATUS_CANCELED = -1; |
||
61 | public const SALE_STATUS_PENDING = 0; |
||
62 | public const SALE_STATUS_COMPLETED = 1; |
||
63 | public const SERVICE_STATUS_PENDING = 0; |
||
64 | public const SERVICE_STATUS_COMPLETED = 1; |
||
65 | public const SERVICE_STATUS_CANCELLED = -1; |
||
66 | public const SERVICE_TYPE_USER = 1; |
||
67 | public const SERVICE_TYPE_COURSE = 2; |
||
68 | public const SERVICE_TYPE_SESSION = 3; |
||
69 | public const SERVICE_TYPE_LP_FINAL_ITEM = 4; |
||
70 | public const CULQI_INTEGRATION_TYPE = 'INTEG'; |
||
71 | public const CULQI_PRODUCTION_TYPE = 'PRODUC'; |
||
72 | public const TAX_APPLIES_TO_ALL = 1; |
||
73 | public const TAX_APPLIES_TO_ONLY_COURSE = 2; |
||
74 | public const TAX_APPLIES_TO_ONLY_SESSION = 3; |
||
75 | public const TAX_APPLIES_TO_ONLY_SERVICES = 4; |
||
76 | public const PAGINATION_PAGE_SIZE = 6; |
||
77 | public const COUPON_DISCOUNT_TYPE_PERCENTAGE = 1; |
||
78 | public const COUPON_DISCOUNT_TYPE_AMOUNT = 2; |
||
79 | public const COUPON_STATUS_ACTIVE = 1; |
||
80 | public const COUPON_STATUS_DISABLE = 0; |
||
81 | |||
82 | public $isAdminPlugin = false; |
||
83 | |||
84 | /** |
||
85 | * BuyCoursesPlugin constructor. |
||
86 | */ |
||
87 | public function __construct() |
||
88 | { |
||
89 | parent::__construct( |
||
90 | '7.1', |
||
91 | " |
||
92 | Jose Angel Ruiz - NoSoloRed (original author) <br/> |
||
93 | Francis Gonzales and Yannick Warnier - BeezNest (integration) <br/> |
||
94 | Alex Aragón - BeezNest (Design icons and css styles) <br/> |
||
95 | Imanol Losada - BeezNest (introduction of sessions purchase) <br/> |
||
96 | Angel Fernando Quiroz Campos - BeezNest (cleanup and new reports) <br/> |
||
97 | José Loguercio Silva - BeezNest (Payouts and buy Services) <br/> |
||
98 | Julio Montoya |
||
99 | ", |
||
100 | [ |
||
101 | 'show_main_menu_tab' => 'boolean', |
||
102 | 'public_main_menu_tab' => 'boolean', |
||
103 | 'include_sessions' => 'boolean', |
||
104 | 'include_services' => 'boolean', |
||
105 | 'paypal_enable' => 'boolean', |
||
106 | 'transfer_enable' => 'boolean', |
||
107 | 'culqi_enable' => 'boolean', |
||
108 | 'commissions_enable' => 'boolean', |
||
109 | 'unregistered_users_enable' => 'boolean', |
||
110 | 'hide_free_text' => 'boolean', |
||
111 | 'hide_shopping_cart_from_course_catalogue' => 'boolean', |
||
112 | 'invoicing_enable' => 'boolean', |
||
113 | 'tax_enable' => 'boolean', |
||
114 | 'use_currency_symbol' => 'boolean', |
||
115 | 'tpv_redsys_enable' => 'boolean', |
||
116 | 'stripe_enable' => 'boolean', |
||
117 | 'cecabank_enable' => 'boolean', |
||
118 | ] |
||
119 | ); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * @return BuyCoursesPlugin |
||
124 | */ |
||
125 | public static function create() |
||
126 | { |
||
127 | static $result = null; |
||
128 | |||
129 | return $result ? $result : $result = new self(); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Check if plugin is enabled. |
||
134 | * |
||
135 | * @param bool $checkEnabled Check if, additionnally to being installed, the plugin is enabled |
||
136 | */ |
||
137 | public function isEnabled(bool $checkEnabled = false): bool |
||
138 | { |
||
139 | return $this->get('paypal_enable') || $this->get('transfer_enable') || $this->get('culqi_enable') || $this->get('stripe_enable') || $this->get('cecabank_enable'); |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * This method creates the tables required to this plugin. |
||
144 | */ |
||
145 | public function install() |
||
146 | { |
||
147 | $tablesToBeCompared = [ |
||
148 | self::TABLE_PAYPAL, |
||
149 | self::TABLE_TRANSFER, |
||
150 | self::TABLE_CULQI, |
||
151 | self::TABLE_ITEM_BENEFICIARY, |
||
152 | self::TABLE_ITEM, |
||
153 | self::TABLE_SALE, |
||
154 | self::TABLE_CURRENCY, |
||
155 | self::TABLE_COMMISSION, |
||
156 | self::TABLE_PAYPAL_PAYOUTS, |
||
157 | self::TABLE_SERVICES, |
||
158 | self::TABLE_SERVICES_SALE, |
||
159 | self::TABLE_GLOBAL_CONFIG, |
||
160 | self::TABLE_INVOICE, |
||
161 | self::TABLE_TPV_REDSYS, |
||
162 | self::TABLE_COUPON, |
||
163 | self::TABLE_COUPON_ITEM, |
||
164 | self::TABLE_COUPON_SERVICE, |
||
165 | self::TABLE_SUBSCRIPTION, |
||
166 | self::TABLE_SUBSCRIPTION_SALE, |
||
167 | self::TABLE_SUBSCRIPTION_PERIOD, |
||
168 | self::TABLE_COUPON_SALE, |
||
169 | self::TABLE_COUPON_SERVICE_SALE, |
||
170 | self::TABLE_COUPON_SUBSCRIPTION_SALE, |
||
171 | self::TABLE_STRIPE, |
||
172 | self::TABLE_TPV_CECABANK, |
||
173 | ]; |
||
174 | $em = Database::getManager(); |
||
175 | $cn = $em->getConnection(); |
||
176 | $sm = $cn->getSchemaManager(); |
||
177 | $tables = $sm->tablesExist($tablesToBeCompared); |
||
178 | |||
179 | if ($tables) { |
||
180 | return false; |
||
181 | } |
||
182 | |||
183 | require_once api_get_path(SYS_PLUGIN_PATH).'buycourses/database.php'; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * This method drops the plugin tables. |
||
188 | */ |
||
189 | public function uninstall() |
||
190 | { |
||
191 | $tablesToBeDeleted = [ |
||
192 | self::TABLE_PAYPAL, |
||
193 | self::TABLE_TRANSFER, |
||
194 | self::TABLE_CULQI, |
||
195 | self::TABLE_ITEM_BENEFICIARY, |
||
196 | self::TABLE_ITEM, |
||
197 | self::TABLE_SALE, |
||
198 | self::TABLE_CURRENCY, |
||
199 | self::TABLE_COMMISSION, |
||
200 | self::TABLE_PAYPAL_PAYOUTS, |
||
201 | self::TABLE_SERVICES_SALE, |
||
202 | self::TABLE_SERVICES, |
||
203 | self::TABLE_GLOBAL_CONFIG, |
||
204 | self::TABLE_INVOICE, |
||
205 | self::TABLE_TPV_REDSYS, |
||
206 | self::TABLE_COUPON, |
||
207 | self::TABLE_COUPON_ITEM, |
||
208 | self::TABLE_COUPON_SERVICE, |
||
209 | self::TABLE_SUBSCRIPTION, |
||
210 | self::TABLE_SUBSCRIPTION_SALE, |
||
211 | self::TABLE_SUBSCRIPTION_PERIOD, |
||
212 | self::TABLE_COUPON_SALE, |
||
213 | self::TABLE_COUPON_SERVICE_SALE, |
||
214 | self::TABLE_COUPON_SUBSCRIPTION_SALE, |
||
215 | self::TABLE_STRIPE, |
||
216 | ]; |
||
217 | |||
218 | foreach ($tablesToBeDeleted as $tableToBeDeleted) { |
||
219 | $table = Database::get_main_table($tableToBeDeleted); |
||
220 | $sql = "DROP TABLE IF EXISTS $table"; |
||
221 | Database::query($sql); |
||
222 | } |
||
223 | $this->manageTab(false); |
||
224 | } |
||
225 | |||
226 | public function update() |
||
227 | { |
||
228 | $table = self::TABLE_GLOBAL_CONFIG; |
||
229 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'global_tax_perc'"; |
||
230 | $res = Database::query($sql); |
||
231 | |||
232 | if (Database::num_rows($res) === 0) { |
||
233 | $sql = "ALTER TABLE $table ADD ( |
||
234 | sale_email varchar(255) NOT NULL, |
||
235 | global_tax_perc int unsigned NOT NULL, |
||
236 | tax_applies_to int unsigned NOT NULL, |
||
237 | tax_name varchar(255) NOT NULL, |
||
238 | seller_name varchar(255) NOT NULL, |
||
239 | seller_id varchar(255) NOT NULL, |
||
240 | seller_address varchar(255) NOT NULL, |
||
241 | seller_email varchar(255) NOT NULL, |
||
242 | next_number_invoice int unsigned NOT NULL, |
||
243 | invoice_series varchar(255) NOT NULL |
||
244 | )"; |
||
245 | $res = Database::query($sql); |
||
246 | if (!$res) { |
||
247 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
248 | } |
||
249 | } |
||
250 | |||
251 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'info_email_extra'"; |
||
252 | $res = Database::query($sql); |
||
253 | |||
254 | if (Database::num_rows($res) === 0) { |
||
255 | $sql = "ALTER TABLE $table ADD (info_email_extra TEXT NOT NULL)"; |
||
256 | $res = Database::query($sql); |
||
257 | if (!$res) { |
||
258 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
259 | } |
||
260 | } |
||
261 | |||
262 | $table = self::TABLE_ITEM; |
||
263 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; |
||
264 | $res = Database::query($sql); |
||
265 | |||
266 | if (Database::num_rows($res) === 0) { |
||
267 | $sql = "ALTER TABLE $table ADD tax_perc int unsigned NULL"; |
||
268 | $res = Database::query($sql); |
||
269 | if (!$res) { |
||
270 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
271 | } |
||
272 | } |
||
273 | |||
274 | $table = self::TABLE_SERVICES; |
||
275 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; |
||
276 | $res = Database::query($sql); |
||
277 | |||
278 | if (Database::num_rows($res) === 0) { |
||
279 | $sql = "ALTER TABLE $table ADD tax_perc int unsigned NULL"; |
||
280 | $res = Database::query($sql); |
||
281 | if (!$res) { |
||
282 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
283 | } |
||
284 | } |
||
285 | |||
286 | $table = self::TABLE_SALE; |
||
287 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; |
||
288 | $res = Database::query($sql); |
||
289 | |||
290 | if (Database::num_rows($res) === 0) { |
||
291 | $sql = "ALTER TABLE $table ADD ( |
||
292 | price_without_tax decimal(10,2) NULL, |
||
293 | tax_perc int unsigned NULL, |
||
294 | tax_amount decimal(10,2) NULL, |
||
295 | invoice int unsigned NULL |
||
296 | )"; |
||
297 | $res = Database::query($sql); |
||
298 | if (!$res) { |
||
299 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
300 | } |
||
301 | } |
||
302 | |||
303 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'price_without_discount'"; |
||
304 | $res = Database::query($sql); |
||
305 | |||
306 | if (Database::num_rows($res) === 0) { |
||
307 | $sql = "ALTER TABLE $table ADD ( |
||
308 | price_without_discount decimal(10,2) NULL, |
||
309 | discount_amount decimal(10,2) NULL |
||
310 | )"; |
||
311 | $res = Database::query($sql); |
||
312 | if (!$res) { |
||
313 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
314 | } |
||
315 | } |
||
316 | |||
317 | $table = self::TABLE_SERVICES_SALE; |
||
318 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; |
||
319 | $res = Database::query($sql); |
||
320 | |||
321 | if (Database::num_rows($res) === 0) { |
||
322 | $sql = "ALTER TABLE $table ADD ( |
||
323 | price_without_tax decimal(10,2) NULL, |
||
324 | tax_perc int unsigned NULL, |
||
325 | tax_amount decimal(10,2) NULL, |
||
326 | invoice int unsigned NULL |
||
327 | )"; |
||
328 | $res = Database::query($sql); |
||
329 | if (!$res) { |
||
330 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
331 | } |
||
332 | } |
||
333 | |||
334 | $sql = "SHOW COLUMNS FROM $table WHERE Field = 'price_without_discount'"; |
||
335 | $res = Database::query($sql); |
||
336 | |||
337 | if (Database::num_rows($res) === 0) { |
||
338 | $sql = "ALTER TABLE $table ADD ( |
||
339 | price_without_discount decimal(10,2) NULL, |
||
340 | discount_amount decimal(10,2) NULL |
||
341 | )"; |
||
342 | $res = Database::query($sql); |
||
343 | if (!$res) { |
||
344 | echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); |
||
345 | } |
||
346 | } |
||
347 | |||
348 | $table = self::TABLE_INVOICE; |
||
349 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
350 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
351 | sale_id int unsigned NOT NULL, |
||
352 | is_service int unsigned NOT NULL, |
||
353 | num_invoice int unsigned NOT NULL, |
||
354 | year int(4) unsigned NOT NULL, |
||
355 | serie varchar(255) NOT NULL, |
||
356 | date_invoice datetime NOT NULL, |
||
357 | PRIMARY KEY (id) |
||
358 | )"; |
||
359 | Database::query($sql); |
||
360 | |||
361 | $table = self::TABLE_TPV_REDSYS; |
||
362 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
363 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
364 | merchantcode varchar(255) NOT NULL, |
||
365 | terminal varchar(255) NOT NULL, |
||
366 | currency varchar(255) NOT NULL, |
||
367 | kc varchar(255) NOT NULL, |
||
368 | url_redsys varchar(255) NOT NULL, |
||
369 | url_redsys_sandbox varchar(255) NOT NULL, |
||
370 | sandbox int unsigned NULL, |
||
371 | PRIMARY KEY (id) |
||
372 | )"; |
||
373 | Database::query($sql); |
||
374 | |||
375 | $sql = "SELECT * FROM $table"; |
||
376 | $res = Database::query($sql); |
||
377 | if (Database::num_rows($res) == 0) { |
||
378 | Database::insert($table, [ |
||
379 | 'url_redsys' => 'https://sis.redsys.es/sis/realizarPago', |
||
380 | 'url_redsys_sandbox' => 'https://sis-t.redsys.es:25443/sis/realizarPago', |
||
381 | ]); |
||
382 | } |
||
383 | |||
384 | $table = self::TABLE_COUPON; |
||
385 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
386 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
387 | code varchar(255) NOT NULL, |
||
388 | discount_type int unsigned NOT NULL, |
||
389 | discount_amount decimal(10, 2) NOT NULL, |
||
390 | valid_start datetime NOT NULL, |
||
391 | valid_end datetime NOT NULL, |
||
392 | delivered varchar(255) NOT NULL, |
||
393 | active tinyint NOT NULL, |
||
394 | PRIMARY KEY (id) |
||
395 | )"; |
||
396 | Database::query($sql); |
||
397 | |||
398 | $table = self::TABLE_COUPON_ITEM; |
||
399 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
400 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
401 | coupon_id int unsigned NOT NULL, |
||
402 | product_type int unsigned NOT NULL, |
||
403 | product_id int unsigned NOT NULL, |
||
404 | PRIMARY KEY (id) |
||
405 | )"; |
||
406 | Database::query($sql); |
||
407 | |||
408 | $table = self::TABLE_COUPON_SERVICE; |
||
409 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
410 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
411 | coupon_id int unsigned NOT NULL, |
||
412 | service_id int unsigned NOT NULL, |
||
413 | PRIMARY KEY (id) |
||
414 | )"; |
||
415 | Database::query($sql); |
||
416 | |||
417 | $table = self::TABLE_SUBSCRIPTION; |
||
418 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
419 | product_type int unsigned NOT NULL, |
||
420 | product_id int unsigned NOT NULL, |
||
421 | duration int unsigned NOT NULL, |
||
422 | currency_id int unsigned NOT NULL, |
||
423 | price decimal(10, 2) NOT NULL, |
||
424 | tax_perc int unsigned, |
||
425 | PRIMARY KEY (product_type, product_id, duration) |
||
426 | )"; |
||
427 | Database::query($sql); |
||
428 | |||
429 | $table = self::TABLE_SUBSCRIPTION_SALE; |
||
430 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
431 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
432 | currency_id int unsigned NOT NULL, |
||
433 | reference varchar(255) NOT NULL, |
||
434 | date datetime NOT NULL, |
||
435 | user_id int unsigned NOT NULL, |
||
436 | product_type int NOT NULL, |
||
437 | product_name varchar(255) NOT NULL, |
||
438 | product_id int unsigned NOT NULL, |
||
439 | price decimal(10,2) NOT NULL, |
||
440 | price_without_tax decimal(10,2) NULL, |
||
441 | tax_perc int unsigned NULL, |
||
442 | tax_amount decimal(10,2) NULL, |
||
443 | status int NOT NULL, |
||
444 | payment_type int NOT NULL, |
||
445 | invoice int NOT NULL, |
||
446 | price_without_discount decimal(10,2), |
||
447 | discount_amount decimal(10,2), |
||
448 | subscription_end datetime NOT NULL, |
||
449 | expired tinyint NULL, |
||
450 | PRIMARY KEY (id) |
||
451 | )"; |
||
452 | Database::query($sql); |
||
453 | |||
454 | $table = self::TABLE_SUBSCRIPTION_PERIOD; |
||
455 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
456 | duration int unsigned NOT NULL, |
||
457 | name varchar(50) NOT NULL, |
||
458 | PRIMARY KEY (duration) |
||
459 | )"; |
||
460 | Database::query($sql); |
||
461 | |||
462 | $table = self::TABLE_COUPON_SALE; |
||
463 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
464 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
465 | coupon_id int unsigned NOT NULL, |
||
466 | sale_id int unsigned NOT NULL, |
||
467 | PRIMARY KEY (id) |
||
468 | )"; |
||
469 | Database::query($sql); |
||
470 | |||
471 | $table = self::TABLE_COUPON_SERVICE_SALE; |
||
472 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
473 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
474 | coupon_id int unsigned NOT NULL, |
||
475 | service_sale_id int unsigned NOT NULL, |
||
476 | PRIMARY KEY (id) |
||
477 | )"; |
||
478 | Database::query($sql); |
||
479 | |||
480 | $table = self::TABLE_COUPON_SUBSCRIPTION_SALE; |
||
481 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
482 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
483 | coupon_id int unsigned NOT NULL, |
||
484 | sale_id int unsigned NOT NULL, |
||
485 | PRIMARY KEY (id) |
||
486 | )"; |
||
487 | Database::query($sql); |
||
488 | |||
489 | $table = self::TABLE_STRIPE; |
||
490 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
491 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
492 | account_id varchar(255) NOT NULL, |
||
493 | secret_key varchar(255) NOT NULL, |
||
494 | endpoint_secret varchar(255) NOT NULL, |
||
495 | PRIMARY KEY (id) |
||
496 | )"; |
||
497 | Database::query($sql); |
||
498 | |||
499 | $sql = "SELECT * FROM $table"; |
||
500 | $res = Database::query($sql); |
||
501 | if (Database::num_rows($res) == 0) { |
||
502 | Database::insert($table, [ |
||
503 | 'account_id' => '', |
||
504 | 'secret_key' => '', |
||
505 | 'endpoint_secret' => '', |
||
506 | ]); |
||
507 | } |
||
508 | |||
509 | $table = self::TABLE_TPV_CECABANK; |
||
510 | $sql = "CREATE TABLE IF NOT EXISTS $table ( |
||
511 | id int unsigned NOT NULL AUTO_INCREMENT, |
||
512 | crypto_key varchar(255) NOT NULL, |
||
513 | merchant_id varchar(255) NOT NULL, |
||
514 | acquirer_bin varchar(255) NOT NULL, |
||
515 | terminal_id varchar(255) NOT NULL, |
||
516 | cypher varchar(255) NOT NULL, |
||
517 | exponent varchar(255) NOT NULL, |
||
518 | supported_payment varchar(255) NOT NULL, |
||
519 | url varchar(255) NOT NULL, |
||
520 | PRIMARY KEY (id) |
||
521 | )"; |
||
522 | Database::query($sql); |
||
523 | |||
524 | Display::addFlash( |
||
525 | Display::return_message( |
||
526 | $this->get_lang('Updated'), |
||
527 | 'info', |
||
528 | false |
||
529 | ) |
||
530 | ); |
||
531 | |||
532 | $fieldlabel = 'buycourses_company'; |
||
533 | $fieldtype = '1'; |
||
534 | $fieldtitle = $this->get_lang('Company'); |
||
535 | $fielddefault = ''; |
||
536 | UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault); |
||
537 | |||
538 | $fieldlabel = 'buycourses_vat'; |
||
539 | $fieldtype = '1'; |
||
540 | $fieldtitle = $this->get_lang('VAT'); |
||
541 | $fielddefault = ''; |
||
542 | UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault); |
||
543 | |||
544 | $fieldlabel = 'buycourses_address'; |
||
545 | $fieldtype = '1'; |
||
546 | $fieldtitle = $this->get_lang('Address'); |
||
547 | $fielddefault = ''; |
||
548 | UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault); |
||
549 | |||
550 | header('Location: '.api_get_path(WEB_PLUGIN_PATH).'buycourses'); |
||
551 | exit; |
||
552 | } |
||
553 | |||
554 | /** |
||
555 | * This function verify if the plugin is enable and return the price info for a course or session in the new grid |
||
556 | * catalog for 1.11.x , the main purpose is to show if a course or session is in sale it shows in the main platform |
||
557 | * course catalog so the old buycourses plugin catalog can be deprecated. |
||
558 | * |
||
559 | * @param int $productId course or session id |
||
560 | * @param int $productType course or session type |
||
561 | * |
||
562 | * @return mixed bool|string html |
||
563 | */ |
||
564 | public function buyCoursesForGridCatalogValidator(int $productId, int $productType) |
||
565 | { |
||
566 | $return = []; |
||
567 | $paypal = $this->get('paypal_enable') === 'true'; |
||
568 | $transfer = $this->get('transfer_enable') === 'true'; |
||
569 | $stripe = $this->get('stripe_enable') === 'true'; |
||
570 | $culqi = $this->get('culqi_enable') === 'true'; |
||
571 | $cecabank = $this->get('cecabank_enable') === 'true'; |
||
572 | $tpv_redsys = $this->get('tpv_redsys_enable') === 'true'; |
||
573 | $hideFree = $this->get('hide_free_text') === 'true'; |
||
574 | |||
575 | if ($paypal || $transfer || $stripe || $culqi || $cecabank || $tpv_redsys) { |
||
576 | $item = $this->getItemByProduct($productId, $productType); |
||
577 | $html = '<div class="buycourses-price">'; |
||
578 | if ($item) { |
||
579 | $html .= '<span class="label label-primary label-price"> |
||
580 | <strong>'.$item['total_price_formatted'].'</strong> |
||
581 | </span>'; |
||
582 | $return['verificator'] = true; |
||
583 | } else { |
||
584 | if ($hideFree == false) { |
||
585 | $html .= '<span class="label label-primary label-free"> |
||
586 | <strong>'.$this->get_lang('Free').'</strong> |
||
587 | </span>'; |
||
588 | } |
||
589 | $return['verificator'] = false; |
||
590 | } |
||
591 | $html .= '</div>'; |
||
592 | $return['html'] = $html; |
||
593 | |||
594 | return $return; |
||
595 | } |
||
596 | |||
597 | return false; |
||
598 | } |
||
599 | |||
600 | /** |
||
601 | * Return the buyCourses plugin button to buy the course. |
||
602 | * |
||
603 | * @return string $html |
||
604 | */ |
||
605 | public function returnBuyCourseButton(int $productId, int $productType) |
||
606 | { |
||
607 | $productId = $productId; |
||
608 | $productType = $productType; |
||
609 | $url = api_get_path(WEB_PLUGIN_PATH).'buycourses/src/process.php?i='.$productId.'&t='.$productType; |
||
610 | $buyButton = Display::returnFontAwesomeIcon('shopping-cart'); |
||
611 | if ($this->get('hide_shopping_cart_from_course_catalogue') === 'true') { |
||
612 | $buyButton = Display::returnFontAwesomeIcon('check').PHP_EOL.get_lang('Subscribe'); |
||
613 | } |
||
614 | $html = '<a class="btn btn-success btn-sm" title="'.$this->get_lang('Buy').'" href="'.$url.'">'. |
||
615 | $buyButton.'</a>'; |
||
616 | |||
617 | return $html; |
||
618 | } |
||
619 | |||
620 | /** |
||
621 | * Get the currency for sales. |
||
622 | * |
||
623 | * @return array The selected currency. Otherwise return false |
||
624 | */ |
||
625 | public function getSelectedCurrency() |
||
626 | { |
||
627 | return Database::select( |
||
628 | '*', |
||
629 | Database::get_main_table(self::TABLE_CURRENCY), |
||
630 | [ |
||
631 | 'where' => ['status = ?' => true], |
||
632 | ], |
||
633 | 'first' |
||
634 | ); |
||
635 | } |
||
636 | |||
637 | /** |
||
638 | * Get a list of currencies. |
||
639 | * |
||
640 | * @return array The currencies. Otherwise return false |
||
641 | */ |
||
642 | public function getCurrencies() |
||
643 | { |
||
644 | return Database::select( |
||
645 | '*', |
||
646 | Database::get_main_table(self::TABLE_CURRENCY) |
||
647 | ); |
||
648 | } |
||
649 | |||
650 | /** |
||
651 | * Save the selected currency. |
||
652 | * |
||
653 | * @param int $selectedId The currency Id |
||
654 | */ |
||
655 | public function saveCurrency(int $selectedId) |
||
656 | { |
||
657 | $currencyTable = Database::get_main_table( |
||
658 | self::TABLE_CURRENCY |
||
659 | ); |
||
660 | |||
661 | Database::update( |
||
662 | $currencyTable, |
||
663 | ['status' => 0] |
||
664 | ); |
||
665 | Database::update( |
||
666 | $currencyTable, |
||
667 | ['status' => 1], |
||
668 | ['id = ?' => $selectedId] |
||
669 | ); |
||
670 | } |
||
671 | |||
672 | /** |
||
673 | * Save the PayPal configuration params. |
||
674 | * |
||
675 | * @return int Rows affected. Otherwise return false |
||
676 | */ |
||
677 | public function savePaypalParams(array $params) |
||
678 | { |
||
679 | return Database::update( |
||
680 | Database::get_main_table(self::TABLE_PAYPAL), |
||
681 | [ |
||
682 | 'username' => $params['username'], |
||
683 | 'password' => $params['password'], |
||
684 | 'signature' => $params['signature'], |
||
685 | 'sandbox' => isset($params['sandbox']), |
||
686 | ], |
||
687 | ['id = ?' => 1] |
||
688 | ); |
||
689 | } |
||
690 | |||
691 | /** |
||
692 | * Gets the stored PayPal params. |
||
693 | * |
||
694 | * @return array |
||
695 | */ |
||
696 | public function getPaypalParams() |
||
697 | { |
||
698 | return Database::select( |
||
699 | '*', |
||
700 | Database::get_main_table(self::TABLE_PAYPAL), |
||
701 | ['id = ?' => 1], |
||
702 | 'first' |
||
703 | ); |
||
704 | } |
||
705 | |||
706 | /** |
||
707 | * Gets the stored TPV Redsys params. |
||
708 | * |
||
709 | * @return array |
||
710 | */ |
||
711 | public function getTpvRedsysParams() |
||
712 | { |
||
713 | return Database::select( |
||
714 | '*', |
||
715 | Database::get_main_table(self::TABLE_TPV_REDSYS), |
||
716 | ['id = ?' => 1], |
||
717 | 'first' |
||
718 | ); |
||
719 | } |
||
720 | |||
721 | /** |
||
722 | * Save the tpv Redsys configuration params. |
||
723 | * |
||
724 | * @return int Rows affected. Otherwise return false |
||
725 | */ |
||
726 | public function saveTpvRedsysParams(array $params) |
||
727 | { |
||
728 | return Database::update( |
||
729 | Database::get_main_table(self::TABLE_TPV_REDSYS), |
||
730 | [ |
||
731 | 'merchantcode' => $params['merchantcode'], |
||
732 | 'terminal' => $params['terminal'], |
||
733 | 'currency' => $params['currency'], |
||
734 | 'kc' => $params['kc'], |
||
735 | 'url_redsys' => $params['url_redsys'], |
||
736 | 'url_redsys_sandbox' => $params['url_redsys_sandbox'], |
||
737 | 'sandbox' => isset($params['sandbox']), |
||
738 | ], |
||
739 | ['id = ?' => 1] |
||
740 | ); |
||
741 | } |
||
742 | |||
743 | /** |
||
744 | * Save Stripe configuration params. |
||
745 | * |
||
746 | * @return int Rows affected. Otherwise return false |
||
747 | */ |
||
748 | public function saveStripeParameters(array $params) |
||
749 | { |
||
750 | return Database::update( |
||
751 | Database::get_main_table(self::TABLE_STRIPE), |
||
752 | [ |
||
753 | 'account_id' => $params['account_id'], |
||
754 | 'secret_key' => $params['secret_key'], |
||
755 | 'endpoint_secret' => $params['endpoint_secret'], |
||
756 | ], |
||
757 | ['id = ?' => 1] |
||
758 | ); |
||
759 | } |
||
760 | |||
761 | /** |
||
762 | * Gets the stored Stripe params. |
||
763 | * |
||
764 | * @return array |
||
765 | */ |
||
766 | public function getStripeParams() |
||
767 | { |
||
768 | return Database::select( |
||
769 | '*', |
||
770 | Database::get_main_table(self::TABLE_STRIPE), |
||
771 | ['id = ?' => 1], |
||
772 | 'first' |
||
773 | ); |
||
774 | } |
||
775 | |||
776 | /** |
||
777 | * Save a transfer account information. |
||
778 | * |
||
779 | * @param array $params The transfer account |
||
780 | * |
||
781 | * @return int Rows affected. Otherwise, return false |
||
782 | */ |
||
783 | public function saveTransferAccount(array $params) |
||
784 | { |
||
785 | return Database::insert( |
||
786 | Database::get_main_table(self::TABLE_TRANSFER), |
||
787 | [ |
||
788 | 'name' => $params['tname'], |
||
789 | 'account' => $params['taccount'], |
||
790 | 'swift' => $params['tswift'], |
||
791 | ] |
||
792 | ); |
||
793 | } |
||
794 | |||
795 | /** |
||
796 | * Save email message information in transfer. |
||
797 | * |
||
798 | * @param array $params The transfer message |
||
799 | * |
||
800 | * @return int Rows affected. Otherwise return false |
||
801 | */ |
||
802 | public function saveTransferInfoEmail(array $params) |
||
803 | { |
||
804 | return Database::update( |
||
805 | Database::get_main_table(self::TABLE_GLOBAL_CONFIG), |
||
806 | ['info_email_extra' => $params['tinfo_email_extra']], |
||
807 | ['id = ?' => 1] |
||
808 | ); |
||
809 | } |
||
810 | |||
811 | /** |
||
812 | * Gets message information for transfer email. |
||
813 | * |
||
814 | * @return array |
||
815 | */ |
||
816 | public function getTransferInfoExtra() |
||
817 | { |
||
818 | return Database::select( |
||
819 | 'info_email_extra AS tinfo_email_extra', |
||
820 | Database::get_main_table(self::TABLE_GLOBAL_CONFIG), |
||
821 | ['id = ?' => 1], |
||
822 | 'first' |
||
823 | ); |
||
824 | } |
||
825 | |||
826 | /** |
||
827 | * Get a list of transfer accounts. |
||
828 | * |
||
829 | * @return array |
||
830 | */ |
||
831 | public function getTransferAccounts() |
||
832 | { |
||
833 | return Database::select( |
||
834 | '*', |
||
835 | Database::get_main_table(self::TABLE_TRANSFER) |
||
836 | ); |
||
837 | } |
||
838 | |||
839 | /** |
||
840 | * Remove a transfer account. |
||
841 | * |
||
842 | * @param int $id The transfer account ID |
||
843 | * |
||
844 | * @return int Rows affected. Otherwise return false |
||
845 | */ |
||
846 | public function deleteTransferAccount(int $id) |
||
847 | { |
||
848 | return Database::delete( |
||
849 | Database::get_main_table(self::TABLE_TRANSFER), |
||
850 | ['id = ?' => $id] |
||
851 | ); |
||
852 | } |
||
853 | |||
854 | /** |
||
855 | * Get registered item data. |
||
856 | * |
||
857 | * @param int $itemId The item ID |
||
858 | * |
||
859 | * @return array |
||
860 | */ |
||
861 | public function getItem(int $itemId) |
||
862 | { |
||
863 | return Database::select( |
||
864 | '*', |
||
865 | Database::get_main_table(self::TABLE_ITEM), |
||
866 | [ |
||
867 | 'where' => ['id = ?' => $itemId], |
||
868 | ], |
||
869 | 'first' |
||
870 | ); |
||
871 | } |
||
872 | |||
873 | /** |
||
874 | * Get the item data. |
||
875 | * |
||
876 | * @param int $productId The item ID |
||
877 | * @param int $itemType The item type |
||
878 | * |
||
879 | * @return array |
||
880 | */ |
||
881 | public function getItemByProduct(int $productId, int $itemType, array $coupon = null) |
||
882 | { |
||
883 | $buyItemTable = Database::get_main_table(self::TABLE_ITEM); |
||
884 | $buyCurrencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
885 | |||
886 | $fakeItemFrom = " |
||
887 | $buyItemTable i |
||
888 | INNER JOIN $buyCurrencyTable c |
||
889 | ON i.currency_id = c.id |
||
890 | "; |
||
891 | |||
892 | $product = Database::select( |
||
893 | ['i.*', 'c.iso_code'], |
||
894 | $fakeItemFrom, |
||
895 | [ |
||
896 | 'where' => [ |
||
897 | 'i.product_id = ? AND i.product_type = ?' => [ |
||
898 | $productId, |
||
899 | $itemType, |
||
900 | ], |
||
901 | ], |
||
902 | ], |
||
903 | 'first' |
||
904 | ); |
||
905 | |||
906 | if (empty($product)) { |
||
907 | return false; |
||
908 | } |
||
909 | |||
910 | $this->setPriceSettings($product, self::TAX_APPLIES_TO_ONLY_COURSE, $coupon); |
||
911 | |||
912 | return $product; |
||
913 | } |
||
914 | |||
915 | /** |
||
916 | * Get registered item data. |
||
917 | * |
||
918 | * @param int $itemId The product ID |
||
919 | * @param int $productType The product type |
||
920 | * |
||
921 | * @return array |
||
922 | */ |
||
923 | public function getSubscriptionItem(int $itemId, int $productType) |
||
924 | { |
||
925 | return Database::select( |
||
926 | '*', |
||
927 | Database::get_main_table(self::TABLE_SUBSCRIPTION), |
||
928 | [ |
||
929 | 'where' => ['product_id = ? AND product_type = ?' => [ |
||
930 | $itemId, |
||
931 | $productType, |
||
932 | ], |
||
933 | ], |
||
934 | ], |
||
935 | 'first' |
||
936 | ); |
||
937 | } |
||
938 | |||
939 | /** |
||
940 | * Get the item data. |
||
941 | * |
||
942 | * @param int $productId The item ID |
||
943 | * @param int $itemType The item type |
||
944 | * @param array $coupon Array with at least 'discount_type' and 'discount_amount' elements |
||
945 | * |
||
946 | * @return array |
||
947 | */ |
||
948 | public function getSubscriptionItemByProduct(int $productId, int $itemType, array $coupon = null) |
||
949 | { |
||
950 | $buySubscriptionItemTable = Database::get_main_table(self::TABLE_SUBSCRIPTION); |
||
951 | $buyCurrencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
952 | |||
953 | $fakeItemFrom = " |
||
954 | $buySubscriptionItemTable s |
||
955 | INNER JOIN $buyCurrencyTable c |
||
956 | ON s.currency_id = c.id |
||
957 | "; |
||
958 | |||
959 | $item = Database::select( |
||
960 | ['s.*', 'c.iso_code'], |
||
961 | $fakeItemFrom, |
||
962 | [ |
||
963 | 'where' => [ |
||
964 | 's.product_id = ? AND s.product_type = ?' => [ |
||
965 | $productId, |
||
966 | $itemType, |
||
967 | ], |
||
968 | ], |
||
969 | ], |
||
970 | 'first' |
||
971 | ); |
||
972 | |||
973 | if (empty($item)) { |
||
974 | return false; |
||
975 | } |
||
976 | |||
977 | $this->setPriceSettings($item, self::TAX_APPLIES_TO_ONLY_COURSE, $coupon); |
||
978 | |||
979 | return $item; |
||
980 | } |
||
981 | |||
982 | /** |
||
983 | * Get the item data. |
||
984 | * |
||
985 | * @param int $productId The item ID |
||
986 | * @param int $itemType The item type |
||
987 | * |
||
988 | * @return array |
||
989 | */ |
||
990 | public function getSubscriptionsItemsByProduct(int $productId, int $itemType) |
||
991 | { |
||
992 | $buySubscriptionItemTable = Database::get_main_table(self::TABLE_SUBSCRIPTION); |
||
993 | $buyCurrencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
994 | |||
995 | $fakeItemFrom = " |
||
996 | $buySubscriptionItemTable s |
||
997 | INNER JOIN $buyCurrencyTable c |
||
998 | ON s.currency_id = c.id |
||
999 | "; |
||
1000 | |||
1001 | $items = Database::select( |
||
1002 | ['s.*', 'c.iso_code'], |
||
1003 | $fakeItemFrom, |
||
1004 | [ |
||
1005 | 'where' => [ |
||
1006 | 's.product_id = ? AND s.product_type = ?' => [ |
||
1007 | $productId, |
||
1008 | $itemType, |
||
1009 | ], |
||
1010 | ], |
||
1011 | ] |
||
1012 | ); |
||
1013 | |||
1014 | for ($i = 0; $i < count($items); $i++) { |
||
1015 | $this->setPriceSettings($items[$i], self::TAX_APPLIES_TO_ONLY_COURSE); |
||
1016 | } |
||
1017 | |||
1018 | if (empty($items)) { |
||
1019 | return false; |
||
1020 | } |
||
1021 | |||
1022 | return $items; |
||
1023 | } |
||
1024 | |||
1025 | /** |
||
1026 | * Get registered item data by duration. |
||
1027 | * |
||
1028 | * @param int $duration The subscription duration |
||
1029 | * |
||
1030 | * @return array |
||
1031 | */ |
||
1032 | public function getSubscriptionsItemsByDuration(int $duration) |
||
1033 | { |
||
1034 | return Database::select( |
||
1035 | '*', |
||
1036 | Database::get_main_table(self::TABLE_SUBSCRIPTION), |
||
1037 | [ |
||
1038 | 'where' => [ |
||
1039 | 'duration = ?' => [$duration], |
||
1040 | ], |
||
1041 | ] |
||
1042 | ); |
||
1043 | } |
||
1044 | |||
1045 | /** |
||
1046 | * List courses details from the configuration page. |
||
1047 | * |
||
1048 | * @return array |
||
1049 | */ |
||
1050 | public function getCourseList(int $first, int $maxResults) |
||
1051 | { |
||
1052 | return $this->getCourses($first, $maxResults); |
||
1053 | } |
||
1054 | |||
1055 | /** |
||
1056 | * Lists current user session details, including each session course details. |
||
1057 | * |
||
1058 | * It can return the number of rows when $typeResult is 'count'. |
||
1059 | * |
||
1060 | * @param string $name Optional. The name filter. |
||
1061 | * @param int $min Optional. The minimum price filter. |
||
1062 | * @param int $max Optional. The maximum price filter. |
||
1063 | * @param string $typeResult Optional. 'all', 'first' or 'count'. |
||
1064 | * |
||
1065 | * @return array|int |
||
1066 | */ |
||
1067 | public function getCatalogSessionList(int $start, int $end, string $name = null, int $min = 0, int $max = 0, string $typeResult = 'all', $sessionCategory = 0) |
||
1068 | { |
||
1069 | $sessions = $this->filterSessionList($start, $end, $name, $min, $max, $typeResult, $sessionCategory); |
||
1070 | |||
1071 | if ($typeResult === 'count') { |
||
1072 | return $sessions; |
||
1073 | } |
||
1074 | |||
1075 | $sessionCatalog = []; |
||
1076 | // loop through all sessions |
||
1077 | foreach ($sessions as $session) { |
||
1078 | $sessionCourses = $session->getCourses(); |
||
1079 | |||
1080 | if (empty($sessionCourses)) { |
||
1081 | continue; |
||
1082 | } |
||
1083 | |||
1084 | $item = $this->getItemByProduct( |
||
1085 | $session->getId(), |
||
1086 | self::PRODUCT_TYPE_SESSION |
||
1087 | ); |
||
1088 | |||
1089 | if (empty($item)) { |
||
1090 | continue; |
||
1091 | } |
||
1092 | |||
1093 | $sessionData = $this->getSessionInfo($session->getId()); |
||
1094 | $sessionData['coach'] = $session->getGeneralCoach()->getCompleteName(); |
||
1095 | $sessionData['enrolled'] = $this->getUserStatusForSession( |
||
1096 | api_get_user_id(), |
||
1097 | $session |
||
1098 | ); |
||
1099 | $sessionData['courses'] = []; |
||
1100 | |||
1101 | foreach ($sessionCourses as $sessionCourse) { |
||
1102 | $course = $sessionCourse->getCourse(); |
||
1103 | |||
1104 | $sessionCourseData = [ |
||
1105 | 'title' => $course->getTitle(), |
||
1106 | 'coaches' => [], |
||
1107 | ]; |
||
1108 | |||
1109 | $userCourseSubscriptions = $session->getUserCourseSubscriptionsByStatus( |
||
1110 | $course, |
||
1111 | Chamilo\CoreBundle\Entity\Session::COACH |
||
1112 | ); |
||
1113 | |||
1114 | foreach ($userCourseSubscriptions as $userCourseSubscription) { |
||
1115 | $user = $userCourseSubscription->getUser(); |
||
1116 | $sessionCourseData['coaches'][] = $user->getCompleteName(); |
||
1117 | } |
||
1118 | $sessionData['courses'][] = $sessionCourseData; |
||
1119 | } |
||
1120 | |||
1121 | $sessionCatalog[] = $sessionData; |
||
1122 | } |
||
1123 | |||
1124 | return $sessionCatalog; |
||
1125 | } |
||
1126 | |||
1127 | /** |
||
1128 | * Lists current user course details. |
||
1129 | * |
||
1130 | * @param string $name Optional. The name filter |
||
1131 | * @param int $min Optional. The minimum price filter |
||
1132 | * @param int $max Optional. The maximum price filter |
||
1133 | * |
||
1134 | * @return array|int |
||
1135 | */ |
||
1136 | public function getCatalogCourseList(int $first, int $pageSize, string $name = null, int $min = 0, int $max = 0, string $typeResult = 'all') |
||
1137 | { |
||
1138 | $courses = $this->filterCourseList($first, $pageSize, $name, $min, $max, $typeResult); |
||
1139 | |||
1140 | if ($typeResult === 'count') { |
||
1141 | return $courses; |
||
1142 | } |
||
1143 | |||
1144 | if (empty($courses)) { |
||
1145 | return []; |
||
1146 | } |
||
1147 | |||
1148 | $courseCatalog = []; |
||
1149 | foreach ($courses as $course) { |
||
1150 | $item = $this->getItemByProduct( |
||
1151 | $course->getId(), |
||
1152 | self::PRODUCT_TYPE_COURSE |
||
1153 | ); |
||
1154 | |||
1155 | if (empty($item)) { |
||
1156 | continue; |
||
1157 | } |
||
1158 | |||
1159 | $courseItem = [ |
||
1160 | 'id' => $course->getId(), |
||
1161 | 'title' => $course->getTitle(), |
||
1162 | 'code' => $course->getCode(), |
||
1163 | 'course_img' => null, |
||
1164 | 'item' => $item, |
||
1165 | 'teachers' => [], |
||
1166 | 'enrolled' => $this->getUserStatusForCourse(api_get_user_id(), $course), |
||
1167 | ]; |
||
1168 | |||
1169 | foreach ($course->getTeachers() as $courseUser) { |
||
1170 | $teacher = $courseUser->getUser(); |
||
1171 | $courseItem['teachers'][] = $teacher->getCompleteName(); |
||
1172 | } |
||
1173 | |||
1174 | // Check images |
||
1175 | $possiblePath = api_get_path(SYS_COURSE_PATH); |
||
1176 | $possiblePath .= $course->getDirectory(); |
||
1177 | $possiblePath .= '/course-pic.png'; |
||
1178 | |||
1179 | if (file_exists($possiblePath)) { |
||
1180 | $courseItem['course_img'] = api_get_path(WEB_COURSE_PATH).$course->getDirectory().'/course-pic.png'; |
||
1181 | } |
||
1182 | $courseCatalog[] = $courseItem; |
||
1183 | } |
||
1184 | |||
1185 | return $courseCatalog; |
||
1186 | } |
||
1187 | |||
1188 | /** |
||
1189 | * Lists current user subscription session details, including each session course details. |
||
1190 | * |
||
1191 | * It can return the number of rows when $typeResult is 'count'. |
||
1192 | * |
||
1193 | * @param int $start Pagination start. |
||
1194 | * @param int $end Pagination end. |
||
1195 | * @param string $name Optional. The name filter. |
||
1196 | * @param string $typeResult Optional. 'all', 'first' or 'count'. |
||
1197 | * @param int $sessionCategory Optional. Session category id |
||
1198 | * |
||
1199 | * @return array|int |
||
1200 | */ |
||
1201 | public function getCatalogSubscriptionSessionList(int $start, int $end, string $name = null, string $typeResult = 'all', int $sessionCategory = 0) |
||
1202 | { |
||
1203 | $sessions = $this->filterSubscriptionSessionList($start, $end, $name, $typeResult, $sessionCategory); |
||
1204 | |||
1205 | if ($typeResult === 'count') { |
||
1206 | return $sessions; |
||
1207 | } |
||
1208 | |||
1209 | $sessionCatalog = []; |
||
1210 | // loop through all sessions |
||
1211 | foreach ($sessions as $session) { |
||
1212 | $sessionCourses = $session->getCourses(); |
||
1213 | |||
1214 | if (empty($sessionCourses)) { |
||
1215 | continue; |
||
1216 | } |
||
1217 | |||
1218 | $item = $this->getSubscriptionItemByProduct( |
||
1219 | $session->getId(), |
||
1220 | self::PRODUCT_TYPE_SESSION |
||
1221 | ); |
||
1222 | |||
1223 | if (empty($item)) { |
||
1224 | continue; |
||
1225 | } |
||
1226 | |||
1227 | $sessionData = $this->getSubscriptionSessionInfo($session->getId()); |
||
1228 | $sessionData['coach'] = $session->getGeneralCoach()->getCompleteName(); |
||
1229 | $sessionData['enrolled'] = $this->getUserStatusForSubscriptionSession( |
||
1230 | api_get_user_id(), |
||
1231 | $session |
||
1232 | ); |
||
1233 | $sessionData['courses'] = []; |
||
1234 | |||
1235 | foreach ($sessionCourses as $sessionCourse) { |
||
1236 | $course = $sessionCourse->getCourse(); |
||
1237 | |||
1238 | $sessionCourseData = [ |
||
1239 | 'title' => $course->getTitle(), |
||
1240 | 'coaches' => [], |
||
1241 | ]; |
||
1242 | |||
1243 | $userCourseSubscriptions = $session->getUserCourseSubscriptionsByStatus( |
||
1244 | $course, |
||
1245 | Chamilo\CoreBundle\Entity\Session::COACH |
||
1246 | ); |
||
1247 | |||
1248 | foreach ($userCourseSubscriptions as $userCourseSubscription) { |
||
1249 | $user = $userCourseSubscription->getUser(); |
||
1250 | $sessionCourseData['coaches'][] = $user->getCompleteName(); |
||
1251 | } |
||
1252 | $sessionData['courses'][] = $sessionCourseData; |
||
1253 | } |
||
1254 | |||
1255 | $sessionCatalog[] = $sessionData; |
||
1256 | } |
||
1257 | |||
1258 | return $sessionCatalog; |
||
1259 | } |
||
1260 | |||
1261 | /** |
||
1262 | * Lists current user subscription course details. |
||
1263 | * |
||
1264 | * @param string $typeResult Optional. 'all', 'first' or 'count'. |
||
1265 | * |
||
1266 | * @return array|int |
||
1267 | */ |
||
1268 | public function getCatalogSubscriptionCourseList(int $first, int $pageSize, string $name = null, string $typeResult = 'all') |
||
1269 | { |
||
1270 | $courses = $this->filterSubscriptionCourseList($first, $pageSize, $name, $typeResult); |
||
1271 | |||
1272 | if ($typeResult === 'count') { |
||
1273 | return $courses; |
||
1274 | } |
||
1275 | |||
1276 | if (empty($courses)) { |
||
1277 | return []; |
||
1278 | } |
||
1279 | |||
1280 | $courseCatalog = []; |
||
1281 | foreach ($courses as $course) { |
||
1282 | $item = $this->getSubscriptionItemByProduct( |
||
1283 | $course->getId(), |
||
1284 | self::PRODUCT_TYPE_COURSE |
||
1285 | ); |
||
1286 | |||
1287 | if (empty($item)) { |
||
1288 | continue; |
||
1289 | } |
||
1290 | |||
1291 | $courseItem = [ |
||
1292 | 'id' => $course->getId(), |
||
1293 | 'title' => $course->getTitle(), |
||
1294 | 'code' => $course->getCode(), |
||
1295 | 'course_img' => null, |
||
1296 | 'item' => $item, |
||
1297 | 'teachers' => [], |
||
1298 | 'enrolled' => $this->getUserStatusForSubscriptionCourse(api_get_user_id(), $course), |
||
1299 | ]; |
||
1300 | |||
1301 | foreach ($course->getTeachers() as $courseUser) { |
||
1302 | $teacher = $courseUser->getUser(); |
||
1303 | $courseItem['teachers'][] = $teacher->getCompleteName(); |
||
1304 | } |
||
1305 | |||
1306 | // Check images |
||
1307 | $possiblePath = api_get_path(SYS_COURSE_PATH); |
||
1308 | $possiblePath .= $course->getDirectory(); |
||
1309 | $possiblePath .= '/course-pic.png'; |
||
1310 | |||
1311 | if (file_exists($possiblePath)) { |
||
1312 | $courseItem['course_img'] = api_get_path(WEB_COURSE_PATH).$course->getDirectory().'/course-pic.png'; |
||
1313 | } |
||
1314 | $courseCatalog[] = $courseItem; |
||
1315 | } |
||
1316 | |||
1317 | return $courseCatalog; |
||
1318 | } |
||
1319 | |||
1320 | public function getPriceWithCurrencyFromIsoCode(float $price, string $isoCode): string |
||
1321 | { |
||
1322 | $useSymbol = $this->get('use_currency_symbol') === 'true'; |
||
1323 | |||
1324 | $result = $isoCode.' '.$price; |
||
1325 | if ($useSymbol) { |
||
1326 | if ($isoCode === 'BRL') { |
||
1327 | $symbol = 'R$'; |
||
1328 | } else { |
||
1329 | $symbol = Symfony\Component\Intl\Intl::getCurrencyBundle()->getCurrencySymbol($isoCode); |
||
1330 | } |
||
1331 | $result = $symbol.' '.$price; |
||
1332 | } |
||
1333 | |||
1334 | return $result; |
||
1335 | } |
||
1336 | |||
1337 | /** |
||
1338 | * Get course info. |
||
1339 | * |
||
1340 | * @return array |
||
1341 | */ |
||
1342 | public function getCourseInfo(int $courseId, array $coupon = null) |
||
1343 | { |
||
1344 | $entityManager = Database::getManager(); |
||
1345 | $course = $entityManager->find('ChamiloCoreBundle:Course', $courseId); |
||
1346 | |||
1347 | if (empty($course)) { |
||
1348 | return []; |
||
1349 | } |
||
1350 | |||
1351 | $item = $this->getItemByProduct( |
||
1352 | $course->getId(), |
||
1353 | self::PRODUCT_TYPE_COURSE, |
||
1354 | $coupon |
||
1355 | ); |
||
1356 | |||
1357 | if (empty($item)) { |
||
1358 | return []; |
||
1359 | } |
||
1360 | |||
1361 | $courseDescription = $entityManager->getRepository('ChamiloCourseBundle:CCourseDescription') |
||
1362 | ->findOneBy( |
||
1363 | [ |
||
1364 | 'cId' => $course->getId(), |
||
1365 | 'sessionId' => 0, |
||
1366 | ], |
||
1367 | [ |
||
1368 | 'descriptionType' => 'ASC', |
||
1369 | ] |
||
1370 | ); |
||
1371 | |||
1372 | $globalParameters = $this->getGlobalParameters(); |
||
1373 | $courseInfo = [ |
||
1374 | 'id' => $course->getId(), |
||
1375 | 'title' => $course->getTitle(), |
||
1376 | 'description' => $courseDescription ? $courseDescription->getContent() : null, |
||
1377 | 'code' => $course->getCode(), |
||
1378 | 'visual_code' => $course->getVisualCode(), |
||
1379 | 'teachers' => [], |
||
1380 | 'item' => $item, |
||
1381 | 'tax_name' => $globalParameters['tax_name'], |
||
1382 | 'tax_enable' => $this->checkTaxEnabledInProduct(self::TAX_APPLIES_TO_ONLY_COURSE), |
||
1383 | 'course_img' => null, |
||
1384 | ]; |
||
1385 | |||
1386 | $courseTeachers = $course->getTeachers(); |
||
1387 | |||
1388 | foreach ($courseTeachers as $teachers) { |
||
1389 | $user = $teachers->getUser(); |
||
1390 | $teacher['id'] = $user->getId(); |
||
1391 | $teacher['name'] = $user->getCompleteName(); |
||
1392 | $courseInfo['teachers'][] = $teacher; |
||
1393 | } |
||
1394 | |||
1395 | $possiblePath = api_get_path(SYS_COURSE_PATH); |
||
1396 | $possiblePath .= $course->getDirectory(); |
||
1397 | $possiblePath .= '/course-pic.png'; |
||
1398 | |||
1399 | if (file_exists($possiblePath)) { |
||
1400 | $courseInfo['course_img'] = api_get_path(WEB_COURSE_PATH).$course->getDirectory().'/course-pic.png'; |
||
1401 | } |
||
1402 | |||
1403 | return $courseInfo; |
||
1404 | } |
||
1405 | |||
1406 | /** |
||
1407 | * Get session info. |
||
1408 | * |
||
1409 | * @return array |
||
1410 | */ |
||
1411 | public function getSessionInfo(int $sessionId, array $coupon = null) |
||
1412 | { |
||
1413 | $entityManager = Database::getManager(); |
||
1414 | $session = $entityManager->find('ChamiloCoreBundle:Session', $sessionId); |
||
1415 | |||
1416 | if (empty($session)) { |
||
1417 | return []; |
||
1418 | } |
||
1419 | |||
1420 | $item = $this->getItemByProduct( |
||
1421 | $session->getId(), |
||
1422 | self::PRODUCT_TYPE_SESSION, |
||
1423 | $coupon |
||
1424 | ); |
||
1425 | |||
1426 | if (empty($item)) { |
||
1427 | return []; |
||
1428 | } |
||
1429 | |||
1430 | $sessionDates = SessionManager::parseSessionDates( |
||
1431 | [ |
||
1432 | 'display_start_date' => $session->getDisplayStartDate(), |
||
1433 | 'display_end_date' => $session->getDisplayEndDate(), |
||
1434 | 'access_start_date' => $session->getAccessStartDate(), |
||
1435 | 'access_end_date' => $session->getAccessEndDate(), |
||
1436 | 'coach_access_start_date' => $session->getCoachAccessStartDate(), |
||
1437 | 'coach_access_end_date' => $session->getCoachAccessEndDate(), |
||
1438 | ] |
||
1439 | ); |
||
1440 | |||
1441 | $globalParameters = $this->getGlobalParameters(); |
||
1442 | $sessionInfo = [ |
||
1443 | 'id' => $session->getId(), |
||
1444 | 'name' => $session->getName(), |
||
1445 | 'description' => $session->getDescription(), |
||
1446 | 'dates' => $sessionDates, |
||
1447 | 'courses' => [], |
||
1448 | 'tax_name' => $globalParameters['tax_name'], |
||
1449 | 'tax_enable' => $this->checkTaxEnabledInProduct(self::TAX_APPLIES_TO_ONLY_SESSION), |
||
1450 | 'image' => null, |
||
1451 | 'nbrCourses' => $session->getNbrCourses(), |
||
1452 | 'nbrUsers' => $session->getNbrUsers(), |
||
1453 | 'item' => $item, |
||
1454 | 'duration' => $session->getDuration(), |
||
1455 | ]; |
||
1456 | |||
1457 | $fieldValue = new ExtraFieldValue('session'); |
||
1458 | $sessionImage = $fieldValue->get_values_by_handler_and_field_variable( |
||
1459 | $session->getId(), |
||
1460 | 'image' |
||
1461 | ); |
||
1462 | |||
1463 | if (!empty($sessionImage)) { |
||
1464 | $sessionInfo['image'] = api_get_path(WEB_UPLOAD_PATH).$sessionImage['value']; |
||
1465 | } |
||
1466 | |||
1467 | $sessionCourses = $session->getCourses(); |
||
1468 | foreach ($sessionCourses as $sessionCourse) { |
||
1469 | $course = $sessionCourse->getCourse(); |
||
1470 | $sessionCourseData = [ |
||
1471 | 'title' => $course->getTitle(), |
||
1472 | 'coaches' => [], |
||
1473 | ]; |
||
1474 | |||
1475 | $userCourseSubscriptions = $session->getUserCourseSubscriptionsByStatus( |
||
1476 | $course, |
||
1477 | Chamilo\CoreBundle\Entity\Session::COACH |
||
1478 | ); |
||
1479 | |||
1480 | foreach ($userCourseSubscriptions as $userCourseSubscription) { |
||
1481 | $user = $userCourseSubscription->getUser(); |
||
1482 | $coaches['id'] = $user->getUserId(); |
||
1483 | $coaches['name'] = $user->getCompleteName(); |
||
1484 | $sessionCourseData['coaches'][] = $coaches; |
||
1485 | } |
||
1486 | |||
1487 | $sessionInfo['courses'][] = $sessionCourseData; |
||
1488 | } |
||
1489 | |||
1490 | return $sessionInfo; |
||
1491 | } |
||
1492 | |||
1493 | /** |
||
1494 | * Get course info. |
||
1495 | * |
||
1496 | * @return array |
||
1497 | */ |
||
1498 | public function getSubscriptionCourseInfo(int $courseId, array $coupon = null) |
||
1499 | { |
||
1500 | $entityManager = Database::getManager(); |
||
1501 | $course = $entityManager->find('ChamiloCoreBundle:Course', $courseId); |
||
1502 | |||
1503 | if (empty($course)) { |
||
1504 | return []; |
||
1505 | } |
||
1506 | |||
1507 | $item = $this->getSubscriptionItemByProduct( |
||
1508 | $course->getId(), |
||
1509 | self::PRODUCT_TYPE_COURSE, |
||
1510 | $coupon |
||
1511 | ); |
||
1512 | |||
1513 | if (empty($item)) { |
||
1514 | return []; |
||
1515 | } |
||
1516 | |||
1517 | $courseDescription = $entityManager->getRepository('ChamiloCourseBundle:CCourseDescription') |
||
1518 | ->findOneBy( |
||
1519 | [ |
||
1520 | 'cId' => $course->getId(), |
||
1521 | 'sessionId' => 0, |
||
1522 | ], |
||
1523 | [ |
||
1524 | 'descriptionType' => 'ASC', |
||
1525 | ] |
||
1526 | ); |
||
1527 | |||
1528 | $globalParameters = $this->getGlobalParameters(); |
||
1529 | $courseInfo = [ |
||
1530 | 'id' => $course->getId(), |
||
1531 | 'title' => $course->getTitle(), |
||
1532 | 'description' => $courseDescription ? $courseDescription->getContent() : null, |
||
1533 | 'code' => $course->getCode(), |
||
1534 | 'visual_code' => $course->getVisualCode(), |
||
1535 | 'teachers' => [], |
||
1536 | 'item' => $item, |
||
1537 | 'tax_name' => $globalParameters['tax_name'], |
||
1538 | 'tax_enable' => $this->checkTaxEnabledInProduct(self::TAX_APPLIES_TO_ONLY_COURSE), |
||
1539 | 'course_img' => null, |
||
1540 | ]; |
||
1541 | |||
1542 | $courseTeachers = $course->getTeachers(); |
||
1543 | |||
1544 | foreach ($courseTeachers as $teachers) { |
||
1545 | $user = $teachers->getUser(); |
||
1546 | $teacher['id'] = $user->getId(); |
||
1547 | $teacher['name'] = $user->getCompleteName(); |
||
1548 | $courseInfo['teachers'][] = $teacher; |
||
1549 | } |
||
1550 | |||
1551 | $possiblePath = api_get_path(SYS_COURSE_PATH); |
||
1552 | $possiblePath .= $course->getDirectory(); |
||
1553 | $possiblePath .= '/course-pic.png'; |
||
1554 | |||
1555 | if (file_exists($possiblePath)) { |
||
1556 | $courseInfo['course_img'] = api_get_path(WEB_COURSE_PATH).$course->getDirectory().'/course-pic.png'; |
||
1557 | } |
||
1558 | |||
1559 | return $courseInfo; |
||
1560 | } |
||
1561 | |||
1562 | /** |
||
1563 | * Get session info. |
||
1564 | * |
||
1565 | * @param array $sessionId The session ID |
||
1566 | * |
||
1567 | * @return array |
||
1568 | */ |
||
1569 | public function getSubscriptionSessionInfo(int $sessionId, array $coupon = null) |
||
1570 | { |
||
1571 | $entityManager = Database::getManager(); |
||
1572 | $session = $entityManager->find('ChamiloCoreBundle:Session', $sessionId); |
||
1573 | |||
1574 | if (empty($session)) { |
||
1575 | return []; |
||
1576 | } |
||
1577 | |||
1578 | $item = $this->getSubscriptionItemByProduct( |
||
1579 | $session->getId(), |
||
1580 | self::PRODUCT_TYPE_SESSION, |
||
1581 | $coupon |
||
1582 | ); |
||
1583 | |||
1584 | if (empty($item)) { |
||
1585 | return []; |
||
1586 | } |
||
1587 | |||
1588 | $sessionDates = SessionManager::parseSessionDates( |
||
1589 | [ |
||
1590 | 'display_start_date' => $session->getDisplayStartDate(), |
||
1591 | 'display_end_date' => $session->getDisplayEndDate(), |
||
1592 | 'access_start_date' => $session->getAccessStartDate(), |
||
1593 | 'access_end_date' => $session->getAccessEndDate(), |
||
1594 | 'coach_access_start_date' => $session->getCoachAccessStartDate(), |
||
1595 | 'coach_access_end_date' => $session->getCoachAccessEndDate(), |
||
1596 | ] |
||
1597 | ); |
||
1598 | |||
1599 | $globalParameters = $this->getGlobalParameters(); |
||
1600 | $sessionInfo = [ |
||
1601 | 'id' => $session->getId(), |
||
1602 | 'name' => $session->getName(), |
||
1603 | 'description' => $session->getDescription(), |
||
1604 | 'dates' => $sessionDates, |
||
1605 | 'courses' => [], |
||
1606 | 'tax_name' => $globalParameters['tax_name'], |
||
1607 | 'tax_enable' => $this->checkTaxEnabledInProduct(self::TAX_APPLIES_TO_ONLY_SESSION), |
||
1608 | 'image' => null, |
||
1609 | 'nbrCourses' => $session->getNbrCourses(), |
||
1610 | 'nbrUsers' => $session->getNbrUsers(), |
||
1611 | 'item' => $item, |
||
1612 | 'duration' => $session->getDuration(), |
||
1613 | ]; |
||
1614 | |||
1615 | $fieldValue = new ExtraFieldValue('session'); |
||
1616 | $sessionImage = $fieldValue->get_values_by_handler_and_field_variable( |
||
1617 | $session->getId(), |
||
1618 | 'image' |
||
1619 | ); |
||
1620 | |||
1621 | if (!empty($sessionImage)) { |
||
1622 | $sessionInfo['image'] = api_get_path(WEB_UPLOAD_PATH).$sessionImage['value']; |
||
1623 | } |
||
1624 | |||
1625 | $sessionCourses = $session->getCourses(); |
||
1626 | foreach ($sessionCourses as $sessionCourse) { |
||
1627 | $course = $sessionCourse->getCourse(); |
||
1628 | $sessionCourseData = [ |
||
1629 | 'title' => $course->getTitle(), |
||
1630 | 'coaches' => [], |
||
1631 | ]; |
||
1632 | |||
1633 | $userCourseSubscriptions = $session->getUserCourseSubscriptionsByStatus( |
||
1634 | $course, |
||
1635 | Chamilo\CoreBundle\Entity\Session::COACH |
||
1636 | ); |
||
1637 | |||
1638 | foreach ($userCourseSubscriptions as $userCourseSubscription) { |
||
1639 | $user = $userCourseSubscription->getUser(); |
||
1640 | $coaches['id'] = $user->getUserId(); |
||
1641 | $coaches['name'] = $user->getCompleteName(); |
||
1642 | $sessionCourseData['coaches'][] = $coaches; |
||
1643 | } |
||
1644 | |||
1645 | $sessionInfo['courses'][] = $sessionCourseData; |
||
1646 | } |
||
1647 | |||
1648 | return $sessionInfo; |
||
1649 | } |
||
1650 | |||
1651 | /** |
||
1652 | * Register a sale. |
||
1653 | * |
||
1654 | * @param int $itemId The product ID |
||
1655 | * @param int $paymentType The payment type |
||
1656 | * @param string $couponId The coupon ID |
||
1657 | * |
||
1658 | * @return bool |
||
1659 | */ |
||
1660 | public function registerSale(int $itemId, int $paymentType, string $couponId = null) |
||
1661 | { |
||
1662 | if (!in_array( |
||
1663 | $paymentType, |
||
1664 | [ |
||
1665 | self::PAYMENT_TYPE_PAYPAL, |
||
1666 | self::PAYMENT_TYPE_TRANSFER, |
||
1667 | self::PAYMENT_TYPE_CULQI, |
||
1668 | self::PAYMENT_TYPE_TPV_REDSYS, |
||
1669 | self::PAYMENT_TYPE_STRIPE, |
||
1670 | self::PAYMENT_TYPE_TPV_CECABANK, |
||
1671 | ] |
||
1672 | ) |
||
1673 | ) { |
||
1674 | return false; |
||
1675 | } |
||
1676 | |||
1677 | $entityManager = Database::getManager(); |
||
1678 | $item = $this->getItem($itemId); |
||
1679 | |||
1680 | if (empty($item)) { |
||
1681 | return false; |
||
1682 | } |
||
1683 | |||
1684 | $productName = ''; |
||
1685 | if ($item['product_type'] == self::PRODUCT_TYPE_COURSE) { |
||
1686 | $course = $entityManager->find('ChamiloCoreBundle:Course', $item['product_id']); |
||
1687 | |||
1688 | if (empty($course)) { |
||
1689 | return false; |
||
1690 | } |
||
1691 | |||
1692 | $productName = $course->getTitle(); |
||
1693 | } elseif ($item['product_type'] == self::PRODUCT_TYPE_SESSION) { |
||
1694 | $session = $entityManager->find('ChamiloCoreBundle:Session', $item['product_id']); |
||
1695 | |||
1696 | if (empty($session)) { |
||
1697 | return false; |
||
1698 | } |
||
1699 | |||
1700 | $productName = $session->getName(); |
||
1701 | } |
||
1702 | |||
1703 | if ($couponId != null) { |
||
1704 | $coupon = $this->getCoupon($couponId, $item['product_type'], $item['product_id']); |
||
1705 | } |
||
1706 | |||
1707 | $couponDiscount = 0; |
||
1708 | $priceWithoutDiscount = 0; |
||
1709 | if ($coupon != null) { |
||
1710 | if ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_AMOUNT) { |
||
1711 | $couponDiscount = $coupon['discount_amount']; |
||
1712 | } elseif ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_PERCENTAGE) { |
||
1713 | $couponDiscount = ($item['price'] * $coupon['discount_amount']) / 100; |
||
1714 | } |
||
1715 | $priceWithoutDiscount = $item['price']; |
||
1716 | } |
||
1717 | $item['price'] = $item['price'] - $couponDiscount; |
||
1718 | $price = $item['price']; |
||
1719 | $priceWithoutTax = null; |
||
1720 | $taxPerc = null; |
||
1721 | $taxAmount = 0; |
||
1722 | $taxEnable = $this->get('tax_enable') === 'true'; |
||
1723 | $globalParameters = $this->getGlobalParameters(); |
||
1724 | $taxAppliesTo = $globalParameters['tax_applies_to']; |
||
1725 | |||
1726 | if ($taxEnable && |
||
1727 | ( |
||
1728 | $taxAppliesTo == self::TAX_APPLIES_TO_ALL || |
||
1729 | ($taxAppliesTo == self::TAX_APPLIES_TO_ONLY_COURSE && $item['product_type'] == self::PRODUCT_TYPE_COURSE) || |
||
1730 | ($taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SESSION && $item['product_type'] == self::PRODUCT_TYPE_SESSION) |
||
1731 | ) |
||
1732 | ) { |
||
1733 | $priceWithoutTax = $item['price']; |
||
1734 | $globalTaxPerc = $globalParameters['global_tax_perc']; |
||
1735 | $precision = 2; |
||
1736 | $taxPerc = is_null($item['tax_perc']) ? $globalTaxPerc : $item['tax_perc']; |
||
1737 | $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); |
||
1738 | $price = $priceWithoutTax + $taxAmount; |
||
1739 | } |
||
1740 | |||
1741 | $values = [ |
||
1742 | 'reference' => $this->generateReference( |
||
1743 | api_get_user_id(), |
||
1744 | $item['product_type'], |
||
1745 | $item['product_id'] |
||
1746 | ), |
||
1747 | 'currency_id' => $item['currency_id'], |
||
1748 | 'date' => api_get_utc_datetime(), |
||
1749 | 'user_id' => api_get_user_id(), |
||
1750 | 'product_type' => $item['product_type'], |
||
1751 | 'product_name' => $productName, |
||
1752 | 'product_id' => $item['product_id'], |
||
1753 | 'price' => $price, |
||
1754 | 'price_without_tax' => $priceWithoutTax, |
||
1755 | 'tax_perc' => $taxPerc, |
||
1756 | 'tax_amount' => $taxAmount, |
||
1757 | 'status' => self::SALE_STATUS_PENDING, |
||
1758 | 'payment_type' => $paymentType, |
||
1759 | 'price_without_discount' => $priceWithoutDiscount, |
||
1760 | 'discount_amount' => $couponDiscount, |
||
1761 | ]; |
||
1762 | |||
1763 | return Database::insert(self::TABLE_SALE, $values); |
||
1764 | } |
||
1765 | |||
1766 | /** |
||
1767 | * Update the sale reference. |
||
1768 | * |
||
1769 | * @return bool |
||
1770 | */ |
||
1771 | public function updateSaleReference(int $saleId, string $saleReference) |
||
1772 | { |
||
1773 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
1774 | |||
1775 | return Database::update( |
||
1776 | $saleTable, |
||
1777 | ['reference' => $saleReference], |
||
1778 | ['id = ?' => $saleId] |
||
1779 | ); |
||
1780 | } |
||
1781 | |||
1782 | /** |
||
1783 | * Get sale data by ID. |
||
1784 | * |
||
1785 | * @return array |
||
1786 | */ |
||
1787 | public function getSale(int $saleId) |
||
1788 | { |
||
1789 | return Database::select( |
||
1790 | '*', |
||
1791 | Database::get_main_table(self::TABLE_SALE), |
||
1792 | [ |
||
1793 | 'where' => ['id = ?' => (int) $saleId], |
||
1794 | ], |
||
1795 | 'first' |
||
1796 | ); |
||
1797 | } |
||
1798 | |||
1799 | /** |
||
1800 | * Get sale data by reference. |
||
1801 | * |
||
1802 | * @return array |
||
1803 | */ |
||
1804 | public function getSaleFromReference(string $reference) |
||
1805 | { |
||
1806 | return Database::select( |
||
1807 | '*', |
||
1808 | Database::get_main_table(self::TABLE_SALE), |
||
1809 | [ |
||
1810 | 'where' => ['reference = ?' => $reference], |
||
1811 | ], |
||
1812 | 'first' |
||
1813 | ); |
||
1814 | } |
||
1815 | |||
1816 | /** |
||
1817 | * Get a list of sales by the payment type. |
||
1818 | * |
||
1819 | * @param int $paymentType The payment type to filter (default : Paypal) |
||
1820 | * |
||
1821 | * @return array The sale list. Otherwise return false |
||
1822 | */ |
||
1823 | public function getSaleListByPaymentType(int $paymentType = self::PAYMENT_TYPE_PAYPAL) |
||
1824 | { |
||
1825 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
1826 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
1827 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
1828 | |||
1829 | $innerJoins = " |
||
1830 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
1831 | INNER JOIN $userTable u ON s.user_id = u.id |
||
1832 | "; |
||
1833 | |||
1834 | return Database::select( |
||
1835 | ['c.iso_code', 'u.firstname', 'u.lastname', 's.*'], |
||
1836 | "$saleTable s $innerJoins", |
||
1837 | [ |
||
1838 | 'where' => [ |
||
1839 | 's.payment_type = ? AND s.status = ?' => [ |
||
1840 | $paymentType, |
||
1841 | self::SALE_STATUS_COMPLETED, |
||
1842 | ], |
||
1843 | ], |
||
1844 | 'order' => 'id DESC', |
||
1845 | ] |
||
1846 | ); |
||
1847 | } |
||
1848 | |||
1849 | /** |
||
1850 | * Get data of sales. |
||
1851 | * |
||
1852 | * @param int $saleId The sale id |
||
1853 | * @param int $isService Check if a service |
||
1854 | * |
||
1855 | * @return array The sale data |
||
1856 | */ |
||
1857 | public function getDataSaleInvoice(int $saleId, int $isService) |
||
1858 | { |
||
1859 | if ($isService) { |
||
1860 | $sale = $this->getServiceSale($saleId); |
||
1861 | $sale['reference'] = $sale['reference']; |
||
1862 | $sale['product_name'] = $sale['service']['name']; |
||
1863 | $sale['payment_type'] = $sale['payment_type']; |
||
1864 | $sale['user_id'] = $sale['buyer']['id']; |
||
1865 | $sale['date'] = $sale['buy_date']; |
||
1866 | } else { |
||
1867 | $sale = $this->getSale($saleId); |
||
1868 | } |
||
1869 | |||
1870 | return $sale; |
||
1871 | } |
||
1872 | |||
1873 | /** |
||
1874 | * Get data of invoice. |
||
1875 | * |
||
1876 | * @param int $saleId The sale id |
||
1877 | * @param int $isService Check if a service |
||
1878 | * |
||
1879 | * @return array The invoice data |
||
1880 | */ |
||
1881 | public function getDataInvoice(int $saleId, int $isService) |
||
1882 | { |
||
1883 | return Database::select( |
||
1884 | '*', |
||
1885 | Database::get_main_table(self::TABLE_INVOICE), |
||
1886 | [ |
||
1887 | 'where' => [ |
||
1888 | 'sale_id = ? AND ' => (int) $saleId, |
||
1889 | 'is_service = ?' => (int) $isService, |
||
1890 | ], |
||
1891 | ], |
||
1892 | 'first' |
||
1893 | ); |
||
1894 | } |
||
1895 | |||
1896 | /** |
||
1897 | * Get invoice numbering. |
||
1898 | * |
||
1899 | * @param int $saleId The sale id |
||
1900 | * @param int $isService Check if a service |
||
1901 | * |
||
1902 | * @return string |
||
1903 | */ |
||
1904 | public function getNumInvoice(int $saleId, int $isService) |
||
1905 | { |
||
1906 | $dataInvoice = $this->getDataInvoice($saleId, $isService); |
||
1907 | if (empty($dataInvoice)) { |
||
1908 | return '-'; |
||
1909 | } |
||
1910 | |||
1911 | return $dataInvoice['serie'].$dataInvoice['year'].'/'.$dataInvoice['num_invoice']; |
||
1912 | } |
||
1913 | |||
1914 | /** |
||
1915 | * Get currency data by ID. |
||
1916 | * |
||
1917 | * @param int $currencyId The currency ID |
||
1918 | * |
||
1919 | * @return array |
||
1920 | */ |
||
1921 | public function getCurrency(int $currencyId) |
||
1922 | { |
||
1923 | return Database::select( |
||
1924 | '*', |
||
1925 | Database::get_main_table(self::TABLE_CURRENCY), |
||
1926 | [ |
||
1927 | 'where' => ['id = ?' => $currencyId], |
||
1928 | ], |
||
1929 | 'first' |
||
1930 | ); |
||
1931 | } |
||
1932 | |||
1933 | /** |
||
1934 | * Complete sale process. Update sale status to completed. |
||
1935 | * |
||
1936 | * @return bool |
||
1937 | */ |
||
1938 | public function completeSale(int $saleId) |
||
1939 | { |
||
1940 | $sale = $this->getSale($saleId); |
||
1941 | |||
1942 | if ($sale['status'] == self::SALE_STATUS_COMPLETED) { |
||
1943 | return true; |
||
1944 | } |
||
1945 | |||
1946 | $saleIsCompleted = false; |
||
1947 | switch ($sale['product_type']) { |
||
1948 | case self::PRODUCT_TYPE_COURSE: |
||
1949 | $course = api_get_course_info_by_id($sale['product_id']); |
||
1950 | $saleIsCompleted = CourseManager::subscribeUser($sale['user_id'], $course['code']); |
||
1951 | break; |
||
1952 | case self::PRODUCT_TYPE_SESSION: |
||
1953 | SessionManager::subscribeUsersToSession( |
||
1954 | $sale['product_id'], |
||
1955 | [$sale['user_id']], |
||
1956 | api_get_session_visibility($sale['product_id']), |
||
1957 | false |
||
1958 | ); |
||
1959 | |||
1960 | $saleIsCompleted = true; |
||
1961 | break; |
||
1962 | } |
||
1963 | |||
1964 | if ($saleIsCompleted) { |
||
1965 | $this->updateSaleStatus($sale['id'], self::SALE_STATUS_COMPLETED); |
||
1966 | if ($this->get('invoicing_enable') === 'true') { |
||
1967 | $this->setInvoice($sale['id']); |
||
1968 | } |
||
1969 | } |
||
1970 | |||
1971 | return $saleIsCompleted; |
||
1972 | } |
||
1973 | |||
1974 | /** |
||
1975 | * Update sale status to canceled. |
||
1976 | * |
||
1977 | * @param int $saleId The sale ID |
||
1978 | */ |
||
1979 | public function cancelSale(int $saleId) |
||
1980 | { |
||
1981 | $this->updateSaleStatus($saleId, self::SALE_STATUS_CANCELED); |
||
1982 | } |
||
1983 | |||
1984 | /** |
||
1985 | * Get payment types. |
||
1986 | */ |
||
1987 | public function getPaymentTypes(bool $onlyActive = false): array |
||
1988 | { |
||
1989 | $types = [ |
||
1990 | self::PAYMENT_TYPE_PAYPAL => 'PayPal', |
||
1991 | self::PAYMENT_TYPE_TRANSFER => $this->get_lang('BankTransfer'), |
||
1992 | self::PAYMENT_TYPE_CULQI => 'Culqi', |
||
1993 | self::PAYMENT_TYPE_TPV_REDSYS => $this->get_lang('TpvPayment'), |
||
1994 | self::PAYMENT_TYPE_STRIPE => 'Stripe', |
||
1995 | self::PAYMENT_TYPE_TPV_CECABANK => $this->get_lang('TpvCecabank'), |
||
1996 | ]; |
||
1997 | |||
1998 | if (!$onlyActive) { |
||
1999 | return $types; |
||
2000 | } |
||
2001 | |||
2002 | if ($this->get('paypal_enable') !== 'true') { |
||
2003 | unset($types[BuyCoursesPlugin::PAYMENT_TYPE_PAYPAL]); |
||
2004 | } |
||
2005 | |||
2006 | if ($this->get('transfer_enable') !== 'true') { |
||
2007 | unset($types[BuyCoursesPlugin::PAYMENT_TYPE_TRANSFER]); |
||
2008 | } |
||
2009 | |||
2010 | if ($this->get('culqi_enable') !== 'true') { |
||
2011 | unset($types[BuyCoursesPlugin::PAYMENT_TYPE_CULQI]); |
||
2012 | } |
||
2013 | |||
2014 | if ($this->get('tpv_redsys_enable') !== 'true' |
||
2015 | || !file_exists(api_get_path(SYS_PLUGIN_PATH).'buycourses/resources/apiRedsys.php') |
||
2016 | ) { |
||
2017 | unset($types[BuyCoursesPlugin::PAYMENT_TYPE_TPV_REDSYS]); |
||
2018 | } |
||
2019 | |||
2020 | if ($this->get('stripe_enable') !== 'true') { |
||
2021 | unset($types[BuyCoursesPlugin::PAYMENT_TYPE_STRIPE]); |
||
2022 | } |
||
2023 | |||
2024 | if ($this->get('cecabank_enable') !== 'true') { |
||
2025 | unset($types[BuyCoursesPlugin::PAYMENT_TYPE_TPV_CECABANK]); |
||
2026 | } |
||
2027 | |||
2028 | return $types; |
||
2029 | } |
||
2030 | |||
2031 | /** |
||
2032 | * Register a invoice. |
||
2033 | * |
||
2034 | * @param int $saleId The sale ID |
||
2035 | * @param int $isService The service type to filter (default : 0) |
||
2036 | */ |
||
2037 | public function setInvoice(int $saleId, int $isService = 0) |
||
2038 | { |
||
2039 | $invoiceTable = Database::get_main_table(self::TABLE_INVOICE); |
||
2040 | $year = date('Y'); |
||
2041 | |||
2042 | $globalParameters = $this->getGlobalParameters(); |
||
2043 | $numInvoice = $globalParameters['next_number_invoice']; |
||
2044 | $serie = $globalParameters['invoice_series']; |
||
2045 | |||
2046 | if (empty($numInvoice)) { |
||
2047 | $item = Database::select( |
||
2048 | ['MAX(num_invoice) AS num_invoice'], |
||
2049 | $invoiceTable, |
||
2050 | [ |
||
2051 | 'where' => ['year = ?' => $year], |
||
2052 | ], |
||
2053 | 'first' |
||
2054 | ); |
||
2055 | |||
2056 | $numInvoice = 1; |
||
2057 | if ($item !== false) { |
||
2058 | $numInvoice = (int) ($item['num_invoice'] + 1); |
||
2059 | } |
||
2060 | } else { |
||
2061 | Database::update( |
||
2062 | Database::get_main_table(self::TABLE_GLOBAL_CONFIG), |
||
2063 | ['next_number_invoice' => 0], |
||
2064 | ['id = ?' => 1] |
||
2065 | ); |
||
2066 | } |
||
2067 | |||
2068 | Database::insert( |
||
2069 | $invoiceTable, |
||
2070 | [ |
||
2071 | 'sale_id' => $saleId, |
||
2072 | 'is_service' => $isService, |
||
2073 | 'num_invoice' => $numInvoice, |
||
2074 | 'year' => $year, |
||
2075 | 'serie' => $serie, |
||
2076 | 'date_invoice' => api_get_utc_datetime(), |
||
2077 | ] |
||
2078 | ); |
||
2079 | |||
2080 | // Record invoice in the sales table |
||
2081 | $table = Database::get_main_table(self::TABLE_SALE); |
||
2082 | if (!empty($isService)) { |
||
2083 | $table = Database::get_main_table(self::TABLE_SERVICES_SALE); |
||
2084 | } |
||
2085 | |||
2086 | Database::update( |
||
2087 | $table, |
||
2088 | ['invoice' => 1], |
||
2089 | ['id = ?' => $saleId] |
||
2090 | ); |
||
2091 | } |
||
2092 | |||
2093 | /** |
||
2094 | * Get Tax's types. |
||
2095 | * |
||
2096 | * @return array |
||
2097 | */ |
||
2098 | public function getTaxAppliesTo() |
||
2099 | { |
||
2100 | return [ |
||
2101 | self::TAX_APPLIES_TO_ALL => $this->get_lang('AllCoursesSessionsAndServices'), |
||
2102 | self::TAX_APPLIES_TO_ONLY_COURSE => $this->get_lang('OnlyCourses'), |
||
2103 | self::TAX_APPLIES_TO_ONLY_SESSION => $this->get_lang('OnlySessions'), |
||
2104 | self::TAX_APPLIES_TO_ONLY_SERVICES => $this->get_lang('OnlyServices'), |
||
2105 | ]; |
||
2106 | } |
||
2107 | |||
2108 | /** |
||
2109 | * Get a list of sales by the status. |
||
2110 | * |
||
2111 | * @param int $status The status to filter |
||
2112 | * |
||
2113 | * @return array The sale list. Otherwise return false |
||
2114 | */ |
||
2115 | public function getSaleListByStatus(int $status = self::SALE_STATUS_PENDING) |
||
2116 | { |
||
2117 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
2118 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2119 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
2120 | |||
2121 | $innerJoins = " |
||
2122 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
2123 | INNER JOIN $userTable u ON s.user_id = u.id |
||
2124 | "; |
||
2125 | |||
2126 | return Database::select( |
||
2127 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
2128 | "$saleTable s $innerJoins", |
||
2129 | [ |
||
2130 | 'where' => ['s.status = ?' => $status], |
||
2131 | 'order' => 'id DESC', |
||
2132 | ] |
||
2133 | ); |
||
2134 | } |
||
2135 | |||
2136 | /** |
||
2137 | * Get the list statuses for sales. |
||
2138 | * |
||
2139 | * @throws Exception |
||
2140 | * |
||
2141 | * @return array |
||
2142 | */ |
||
2143 | public function getSaleListReport(string $dateStart = null, string $dateEnd = null) |
||
2144 | { |
||
2145 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
2146 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2147 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
2148 | $innerJoins = " |
||
2149 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
2150 | INNER JOIN $userTable u ON s.user_id = u.id |
||
2151 | "; |
||
2152 | $list = Database::select( |
||
2153 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
2154 | "$saleTable s $innerJoins", |
||
2155 | [ |
||
2156 | 'order' => 'id DESC', |
||
2157 | ] |
||
2158 | ); |
||
2159 | $listExportTemp = []; |
||
2160 | $listExport = []; |
||
2161 | $textStatus = null; |
||
2162 | $paymentTypes = $this->getPaymentTypes(); |
||
2163 | $productTypes = $this->getProductTypes(); |
||
2164 | foreach ($list as $item) { |
||
2165 | $statusSaleOrder = $item['status']; |
||
2166 | switch ($statusSaleOrder) { |
||
2167 | case 0: |
||
2168 | $textStatus = $this->get_lang('SaleStatusPending'); |
||
2169 | break; |
||
2170 | case 1: |
||
2171 | $textStatus = $this->get_lang('SaleStatusCompleted'); |
||
2172 | break; |
||
2173 | case -1: |
||
2174 | $textStatus = $this->get_lang('SaleStatusCanceled'); |
||
2175 | break; |
||
2176 | } |
||
2177 | $dateFilter = new DateTime($item['date']); |
||
2178 | $listExportTemp[] = [ |
||
2179 | 'id' => $item['id'], |
||
2180 | 'reference' => $item['reference'], |
||
2181 | 'status' => $textStatus, |
||
2182 | 'status_filter' => $item['status'], |
||
2183 | 'date' => $dateFilter->format('Y-m-d'), |
||
2184 | 'order_time' => $dateFilter->format('H:i:s'), |
||
2185 | 'price' => $item['iso_code'].' '.$item['price'], |
||
2186 | 'product_type' => $productTypes[$item['product_type']], |
||
2187 | 'product_name' => $item['product_name'], |
||
2188 | 'payment_type' => $paymentTypes[$item['payment_type']], |
||
2189 | 'complete_user_name' => api_get_person_name($item['firstname'], $item['lastname']), |
||
2190 | 'email' => $item['email'], |
||
2191 | ]; |
||
2192 | } |
||
2193 | $listExport[] = [ |
||
2194 | get_lang('Number'), |
||
2195 | $this->get_lang('OrderStatus'), |
||
2196 | $this->get_lang('OrderDate'), |
||
2197 | $this->get_lang('OrderTime'), |
||
2198 | $this->get_lang('PaymentMethod'), |
||
2199 | $this->get_lang('SalePrice'), |
||
2200 | $this->get_lang('ProductType'), |
||
2201 | $this->get_lang('ProductName'), |
||
2202 | $this->get_lang('UserName'), |
||
2203 | get_lang('Email'), |
||
2204 | ]; |
||
2205 | //Validation Export |
||
2206 | $dateStart = strtotime($dateStart); |
||
2207 | $dateEnd = strtotime($dateEnd); |
||
2208 | foreach ($listExportTemp as $item) { |
||
2209 | $dateFilter = strtotime($item['date']); |
||
2210 | if (($dateFilter >= $dateStart) && ($dateFilter <= $dateEnd)) { |
||
2211 | $listExport[] = [ |
||
2212 | 'id' => $item['id'], |
||
2213 | 'status' => $item['status'], |
||
2214 | 'date' => $item['date'], |
||
2215 | 'order_time' => $item['order_time'], |
||
2216 | 'payment_type' => $item['payment_type'], |
||
2217 | 'price' => $item['price'], |
||
2218 | 'product_type' => $item['product_type'], |
||
2219 | 'product_name' => $item['product_name'], |
||
2220 | 'complete_user_name' => $item['complete_user_name'], |
||
2221 | 'email' => $item['email'], |
||
2222 | ]; |
||
2223 | } |
||
2224 | } |
||
2225 | |||
2226 | return $listExport; |
||
2227 | } |
||
2228 | |||
2229 | /** |
||
2230 | * Get the statuses for sales. |
||
2231 | * |
||
2232 | * @return array |
||
2233 | */ |
||
2234 | public function getSaleStatuses() |
||
2235 | { |
||
2236 | return [ |
||
2237 | self::SALE_STATUS_CANCELED => $this->get_lang('SaleStatusCanceled'), |
||
2238 | self::SALE_STATUS_PENDING => $this->get_lang('SaleStatusPending'), |
||
2239 | self::SALE_STATUS_COMPLETED => $this->get_lang('SaleStatusCompleted'), |
||
2240 | ]; |
||
2241 | } |
||
2242 | |||
2243 | /** |
||
2244 | * Get the statuses for Payouts. |
||
2245 | * |
||
2246 | * @return array |
||
2247 | */ |
||
2248 | public function getPayoutStatuses() |
||
2249 | { |
||
2250 | return [ |
||
2251 | self::PAYOUT_STATUS_CANCELED => $this->get_lang('PayoutStatusCanceled'), |
||
2252 | self::PAYOUT_STATUS_PENDING => $this->get_lang('PayoutStatusPending'), |
||
2253 | self::PAYOUT_STATUS_COMPLETED => $this->get_lang('PayoutStatusCompleted'), |
||
2254 | ]; |
||
2255 | } |
||
2256 | |||
2257 | /** |
||
2258 | * Get the list of product types. |
||
2259 | * |
||
2260 | * @return array |
||
2261 | */ |
||
2262 | public function getProductTypes() |
||
2263 | { |
||
2264 | return [ |
||
2265 | self::PRODUCT_TYPE_COURSE => get_lang('Course'), |
||
2266 | self::PRODUCT_TYPE_SESSION => get_lang('Session'), |
||
2267 | ]; |
||
2268 | } |
||
2269 | |||
2270 | /** |
||
2271 | * Get the list of service types. |
||
2272 | * |
||
2273 | * @return array |
||
2274 | */ |
||
2275 | public function getServiceTypes() |
||
2276 | { |
||
2277 | return [ |
||
2278 | self::SERVICE_TYPE_USER => get_lang('User'), |
||
2279 | self::SERVICE_TYPE_COURSE => get_lang('Course'), |
||
2280 | self::SERVICE_TYPE_SESSION => get_lang('Session'), |
||
2281 | self::SERVICE_TYPE_LP_FINAL_ITEM => get_lang('TemplateTitleCertificate'), |
||
2282 | ]; |
||
2283 | } |
||
2284 | |||
2285 | /** |
||
2286 | * Get the list of coupon status. |
||
2287 | * |
||
2288 | * @return array |
||
2289 | */ |
||
2290 | public function getCouponStatuses() |
||
2291 | { |
||
2292 | return [ |
||
2293 | self::COUPON_STATUS_ACTIVE => $this->get_lang('CouponActive'), |
||
2294 | self::COUPON_STATUS_DISABLE => $this->get_lang('CouponDisabled'), |
||
2295 | ]; |
||
2296 | } |
||
2297 | |||
2298 | /** |
||
2299 | * Get the list of coupon discount types. |
||
2300 | * |
||
2301 | * @return array |
||
2302 | */ |
||
2303 | public function getCouponDiscountTypes() |
||
2304 | { |
||
2305 | return [ |
||
2306 | self::COUPON_DISCOUNT_TYPE_PERCENTAGE => $this->get_lang('CouponPercentage'), |
||
2307 | self::COUPON_DISCOUNT_TYPE_AMOUNT => $this->get_lang('CouponAmount'), |
||
2308 | ]; |
||
2309 | } |
||
2310 | |||
2311 | /** |
||
2312 | * Generates a random text (used for order references). |
||
2313 | * |
||
2314 | * @param int $length Optional. Length of characters (defaults to 6) |
||
2315 | * @param bool $lowercase Optional. Include lowercase characters |
||
2316 | * @param bool $uppercase Optional. Include uppercase characters |
||
2317 | * @param bool $numbers Optional. Include numbers |
||
2318 | */ |
||
2319 | public static function randomText( |
||
2320 | int $length = 6, |
||
2321 | bool $lowercase = true, |
||
2322 | bool $uppercase = true, |
||
2323 | bool $numbers = true |
||
2324 | ): string { |
||
2325 | $salt = $lowercase ? 'abchefghknpqrstuvwxyz' : ''; |
||
2326 | $salt .= $uppercase ? 'ACDEFHKNPRSTUVWXYZ' : ''; |
||
2327 | $salt .= $numbers ? (strlen($salt) ? '2345679' : '0123456789') : ''; |
||
2328 | |||
2329 | if (strlen($salt) == 0) { |
||
2330 | return ''; |
||
2331 | } |
||
2332 | |||
2333 | $str = ''; |
||
2334 | |||
2335 | srand((float) microtime() * 1000000); |
||
2336 | |||
2337 | for ($i = 0; $i < $length; $i++) { |
||
2338 | $numbers = rand(0, strlen($salt) - 1); |
||
2339 | $str .= substr($salt, $numbers, 1); |
||
2340 | } |
||
2341 | |||
2342 | return $str; |
||
2343 | } |
||
2344 | |||
2345 | /** |
||
2346 | * Generates an order reference. |
||
2347 | * |
||
2348 | * @param int $userId The user ID |
||
2349 | * @param int $productType The course/session type |
||
2350 | * @param int $productId The course/session ID |
||
2351 | */ |
||
2352 | public function generateReference(int $userId, int $productType, int $productId): string |
||
2353 | { |
||
2354 | return vsprintf( |
||
2355 | '%d-%d-%d-%s', |
||
2356 | [$userId, $productType, $productId, self::randomText()] |
||
2357 | ); |
||
2358 | } |
||
2359 | |||
2360 | /** |
||
2361 | * Get a list of sales by the user. |
||
2362 | * |
||
2363 | * @param string $term The search term |
||
2364 | * |
||
2365 | * @return array The sale list. Otherwise return false |
||
2366 | */ |
||
2367 | public function getSaleListByUser(string $term) |
||
2368 | { |
||
2369 | $term = trim($term); |
||
2370 | |||
2371 | if (empty($term)) { |
||
2372 | return []; |
||
2373 | } |
||
2374 | |||
2375 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
2376 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2377 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
2378 | $innerJoins = " |
||
2379 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
2380 | INNER JOIN $userTable u ON s.user_id = u.id |
||
2381 | "; |
||
2382 | |||
2383 | return Database::select( |
||
2384 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
2385 | "$saleTable s $innerJoins", |
||
2386 | [ |
||
2387 | 'where' => [ |
||
2388 | 'u.username LIKE %?% OR ' => $term, |
||
2389 | 'u.lastname LIKE %?% OR ' => $term, |
||
2390 | 'u.firstname LIKE %?%' => $term, |
||
2391 | ], |
||
2392 | 'order' => 'id DESC', |
||
2393 | ] |
||
2394 | ); |
||
2395 | } |
||
2396 | |||
2397 | /** |
||
2398 | * Get a list of sales by the user id. |
||
2399 | * |
||
2400 | * @param int $id The user id |
||
2401 | * |
||
2402 | * @return array The sale list. Otherwise return false |
||
2403 | */ |
||
2404 | public function getSaleListByUserId(int $id) |
||
2405 | { |
||
2406 | if (empty($id)) { |
||
2407 | return []; |
||
2408 | } |
||
2409 | |||
2410 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
2411 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2412 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
2413 | |||
2414 | $innerJoins = " |
||
2415 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
2416 | INNER JOIN $userTable u ON s.user_id = u.id |
||
2417 | "; |
||
2418 | |||
2419 | return Database::select( |
||
2420 | ['c.iso_code', 'u.firstname', 'u.lastname', 's.*'], |
||
2421 | "$saleTable s $innerJoins", |
||
2422 | [ |
||
2423 | 'where' => [ |
||
2424 | 'u.id = ? AND s.status = ?' => [(int) $id, self::SALE_STATUS_COMPLETED], |
||
2425 | ], |
||
2426 | 'order' => 'id DESC', |
||
2427 | ] |
||
2428 | ); |
||
2429 | } |
||
2430 | |||
2431 | /** |
||
2432 | * Get a list of sales by date range. |
||
2433 | * |
||
2434 | * @return array The sale list. Otherwise return false |
||
2435 | */ |
||
2436 | public function getSaleListByDate(string $dateStart, string $dateEnd) |
||
2437 | { |
||
2438 | $dateStart = trim($dateStart); |
||
2439 | $dateEnd = trim($dateEnd); |
||
2440 | if (empty($dateStart)) { |
||
2441 | return []; |
||
2442 | } |
||
2443 | if (empty($dateEnd)) { |
||
2444 | return []; |
||
2445 | } |
||
2446 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
2447 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2448 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
2449 | $innerJoins = " |
||
2450 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
2451 | INNER JOIN $userTable u ON s.user_id = u.id |
||
2452 | "; |
||
2453 | |||
2454 | return Database::select( |
||
2455 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
2456 | "$saleTable s $innerJoins", |
||
2457 | [ |
||
2458 | 'where' => [ |
||
2459 | 's.date BETWEEN ? AND ' => $dateStart, |
||
2460 | ' ? ' => $dateEnd, |
||
2461 | ], |
||
2462 | 'order' => 'id DESC', |
||
2463 | ] |
||
2464 | ); |
||
2465 | } |
||
2466 | |||
2467 | /** |
||
2468 | * Get a list of sales by the user Email. |
||
2469 | * |
||
2470 | * @param string $term The search term |
||
2471 | * |
||
2472 | * @return array The sale list. Otherwise return false |
||
2473 | */ |
||
2474 | public function getSaleListByEmail(string $term) |
||
2475 | { |
||
2476 | $term = trim($term); |
||
2477 | if (empty($term)) { |
||
2478 | return []; |
||
2479 | } |
||
2480 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
2481 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2482 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
2483 | $innerJoins = " |
||
2484 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
2485 | INNER JOIN $userTable u ON s.user_id = u.id |
||
2486 | "; |
||
2487 | |||
2488 | return Database::select( |
||
2489 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
2490 | "$saleTable s $innerJoins", |
||
2491 | [ |
||
2492 | 'where' => [ |
||
2493 | 'u.email LIKE %?% ' => $term, |
||
2494 | ], |
||
2495 | 'order' => 'id DESC', |
||
2496 | ] |
||
2497 | ); |
||
2498 | } |
||
2499 | |||
2500 | /** |
||
2501 | * Convert the course info to array with necessary course data for save item. |
||
2502 | * |
||
2503 | * @param array $defaultCurrency Optional. Currency data |
||
2504 | * |
||
2505 | * @return array |
||
2506 | */ |
||
2507 | public function getCourseForConfiguration(Course $course, array $defaultCurrency = null) |
||
2508 | { |
||
2509 | $courseItem = [ |
||
2510 | 'item_id' => null, |
||
2511 | 'course_id' => $course->getId(), |
||
2512 | 'course_visual_code' => $course->getVisualCode(), |
||
2513 | 'course_code' => $course->getCode(), |
||
2514 | 'course_title' => $course->getTitle(), |
||
2515 | 'course_directory' => $course->getDirectory(), |
||
2516 | 'course_visibility' => $course->getVisibility(), |
||
2517 | 'visible' => false, |
||
2518 | 'currency' => empty($defaultCurrency) ? null : $defaultCurrency['iso_code'], |
||
2519 | 'price' => 0.00, |
||
2520 | 'tax_perc' => null, |
||
2521 | ]; |
||
2522 | |||
2523 | $item = $this->getItemByProduct($course->getId(), self::PRODUCT_TYPE_COURSE); |
||
2524 | |||
2525 | if ($item !== false) { |
||
2526 | $courseItem['item_id'] = $item['id']; |
||
2527 | $courseItem['visible'] = true; |
||
2528 | $courseItem['currency'] = $item['iso_code']; |
||
2529 | $courseItem['price'] = $item['price']; |
||
2530 | $courseItem['tax_perc'] = $item['tax_perc']; |
||
2531 | } |
||
2532 | |||
2533 | return $courseItem; |
||
2534 | } |
||
2535 | |||
2536 | /** |
||
2537 | * Convert the session info to array with necessary session data for save item. |
||
2538 | * |
||
2539 | * @param Session $session The session data |
||
2540 | * @param array $defaultCurrency Optional. Currency data |
||
2541 | * |
||
2542 | * @return array |
||
2543 | */ |
||
2544 | public function getSessionForConfiguration(Session $session, array $defaultCurrency = null) |
||
2545 | { |
||
2546 | $buyItemTable = Database::get_main_table(self::TABLE_ITEM); |
||
2547 | $buyCurrencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2548 | |||
2549 | $fakeItemFrom = " |
||
2550 | $buyItemTable i |
||
2551 | INNER JOIN $buyCurrencyTable c ON i.currency_id = c.id |
||
2552 | "; |
||
2553 | |||
2554 | $sessionItem = [ |
||
2555 | 'item_id' => null, |
||
2556 | 'session_id' => $session->getId(), |
||
2557 | 'session_name' => $session->getName(), |
||
2558 | 'session_visibility' => $session->getVisibility(), |
||
2559 | 'session_display_start_date' => null, |
||
2560 | 'session_display_end_date' => null, |
||
2561 | 'visible' => false, |
||
2562 | 'currency' => empty($defaultCurrency) ? null : $defaultCurrency['iso_code'], |
||
2563 | 'price' => 0.00, |
||
2564 | 'tax_perc' => null, |
||
2565 | ]; |
||
2566 | |||
2567 | $displayStartDate = $session->getDisplayStartDate(); |
||
2568 | |||
2569 | if (!empty($displayStartDate)) { |
||
2570 | $sessionItem['session_display_start_date'] = api_format_date( |
||
2571 | $session->getDisplayStartDate()->format('Y-m-d h:i:s') |
||
2572 | ); |
||
2573 | } |
||
2574 | |||
2575 | $displayEndDate = $session->getDisplayEndDate(); |
||
2576 | |||
2577 | if (!empty($displayEndDate)) { |
||
2578 | $sessionItem['session_display_end_date'] = api_format_date( |
||
2579 | $session->getDisplayEndDate()->format('Y-m-d h:i:s'), |
||
2580 | DATE_TIME_FORMAT_LONG_24H |
||
2581 | ); |
||
2582 | } |
||
2583 | |||
2584 | $item = Database::select( |
||
2585 | ['i.*', 'c.iso_code'], |
||
2586 | $fakeItemFrom, |
||
2587 | [ |
||
2588 | 'where' => [ |
||
2589 | 'i.product_id = ? AND ' => $session->getId(), |
||
2590 | 'i.product_type = ?' => self::PRODUCT_TYPE_SESSION, |
||
2591 | ], |
||
2592 | ], |
||
2593 | 'first' |
||
2594 | ); |
||
2595 | |||
2596 | if ($item !== false) { |
||
2597 | $sessionItem['item_id'] = $item['id']; |
||
2598 | $sessionItem['visible'] = true; |
||
2599 | $sessionItem['currency'] = $item['iso_code']; |
||
2600 | $sessionItem['price'] = $item['price']; |
||
2601 | $sessionItem['tax_perc'] = $item['tax_perc']; |
||
2602 | } |
||
2603 | |||
2604 | return $sessionItem; |
||
2605 | } |
||
2606 | |||
2607 | /** |
||
2608 | * Get all beneficiaries for a item. |
||
2609 | * |
||
2610 | * @param int $itemId The item ID |
||
2611 | * |
||
2612 | * @return array The beneficiaries. Otherwise return false |
||
2613 | */ |
||
2614 | public function getItemBeneficiaries(int $itemId) |
||
2615 | { |
||
2616 | $beneficiaryTable = Database::get_main_table(self::TABLE_ITEM_BENEFICIARY); |
||
2617 | |||
2618 | return Database::select( |
||
2619 | '*', |
||
2620 | $beneficiaryTable, |
||
2621 | [ |
||
2622 | 'where' => [ |
||
2623 | 'item_id = ?' => $itemId, |
||
2624 | ], |
||
2625 | ] |
||
2626 | ); |
||
2627 | } |
||
2628 | |||
2629 | /** |
||
2630 | * Delete a item with its beneficiaries. |
||
2631 | * |
||
2632 | * @param int $itemId The item ID |
||
2633 | * |
||
2634 | * @return int The number of affected rows. Otherwise return false |
||
2635 | */ |
||
2636 | public function deleteItem(int $itemId) |
||
2637 | { |
||
2638 | $itemTable = Database::get_main_table(self::TABLE_ITEM); |
||
2639 | $affectedRows = Database::delete( |
||
2640 | $itemTable, |
||
2641 | ['id = ?' => $itemId] |
||
2642 | ); |
||
2643 | |||
2644 | if (!$affectedRows) { |
||
2645 | return false; |
||
2646 | } |
||
2647 | |||
2648 | return $this->deleteItemBeneficiaries($itemId); |
||
2649 | } |
||
2650 | |||
2651 | /** |
||
2652 | * Register a item. |
||
2653 | * |
||
2654 | * @param array $itemData The item data |
||
2655 | * |
||
2656 | * @return int The item ID. Otherwise return false |
||
2657 | */ |
||
2658 | public function registerItem(array $itemData) |
||
2659 | { |
||
2660 | $itemTable = Database::get_main_table(self::TABLE_ITEM); |
||
2661 | |||
2662 | return Database::insert($itemTable, $itemData); |
||
2663 | } |
||
2664 | |||
2665 | /** |
||
2666 | * Update the item data by product. |
||
2667 | * |
||
2668 | * @param array $itemData The item data to be updated |
||
2669 | * @param int $productId The product ID |
||
2670 | * @param int $productType The type of product |
||
2671 | * |
||
2672 | * @return int The number of affected rows. Otherwise return false |
||
2673 | */ |
||
2674 | public function updateItem(array $itemData, int $productId, int $productType) |
||
2675 | { |
||
2676 | $itemTable = Database::get_main_table(self::TABLE_ITEM); |
||
2677 | |||
2678 | return Database::update( |
||
2679 | $itemTable, |
||
2680 | $itemData, |
||
2681 | [ |
||
2682 | 'product_id = ? AND ' => $productId, |
||
2683 | 'product_type' => $productType, |
||
2684 | ] |
||
2685 | ); |
||
2686 | } |
||
2687 | |||
2688 | /** |
||
2689 | * Remove all beneficiaries for a item. |
||
2690 | * |
||
2691 | * @param int $itemId The user ID |
||
2692 | * |
||
2693 | * @return int The number of affected rows. Otherwise return false |
||
2694 | */ |
||
2695 | public function deleteItemBeneficiaries(int $itemId) |
||
2696 | { |
||
2697 | $beneficiaryTable = Database::get_main_table(self::TABLE_ITEM_BENEFICIARY); |
||
2698 | |||
2699 | return Database::delete( |
||
2700 | $beneficiaryTable, |
||
2701 | ['item_id = ?' => $itemId] |
||
2702 | ); |
||
2703 | } |
||
2704 | |||
2705 | /** |
||
2706 | * Register the beneficiaries users with the sale of item. |
||
2707 | * |
||
2708 | * @param int $itemId The item ID |
||
2709 | * @param array $userIds The beneficiary user ID and Teachers commissions if enabled |
||
2710 | */ |
||
2711 | public function registerItemBeneficiaries(int $itemId, array $userIds) |
||
2712 | { |
||
2713 | $beneficiaryTable = Database::get_main_table(self::TABLE_ITEM_BENEFICIARY); |
||
2714 | |||
2715 | $this->deleteItemBeneficiaries($itemId); |
||
2716 | |||
2717 | foreach ($userIds as $userId => $commissions) { |
||
2718 | Database::insert( |
||
2719 | $beneficiaryTable, |
||
2720 | [ |
||
2721 | 'item_id' => $itemId, |
||
2722 | 'user_id' => (int) $userId, |
||
2723 | 'commissions' => (int) $commissions, |
||
2724 | ] |
||
2725 | ); |
||
2726 | } |
||
2727 | } |
||
2728 | |||
2729 | /** |
||
2730 | * Check if a course is valid for sale. |
||
2731 | * |
||
2732 | * @param Course $course The course |
||
2733 | * |
||
2734 | * @return bool |
||
2735 | */ |
||
2736 | public function isValidCourse(Course $course) |
||
2737 | { |
||
2738 | $courses = $this->getCourses(); |
||
2739 | |||
2740 | foreach ($courses as $_c) { |
||
2741 | if ($_c->getCode() === $course->getCode()) { |
||
2742 | return true; |
||
2743 | } |
||
2744 | } |
||
2745 | |||
2746 | return false; |
||
2747 | } |
||
2748 | |||
2749 | /** |
||
2750 | * Gets the beneficiaries with commissions and current paypal accounts by sale. |
||
2751 | * |
||
2752 | * @param int $saleId The sale ID |
||
2753 | * |
||
2754 | * @return array |
||
2755 | */ |
||
2756 | public function getBeneficiariesBySale(int $saleId) |
||
2757 | { |
||
2758 | $sale = $this->getSale($saleId); |
||
2759 | $item = $this->getItemByProduct($sale['product_id'], $sale['product_type']); |
||
2760 | $itemBeneficiaries = $this->getItemBeneficiaries($item['id']); |
||
2761 | |||
2762 | return $itemBeneficiaries; |
||
2763 | } |
||
2764 | |||
2765 | /** |
||
2766 | * gets all payouts. |
||
2767 | * |
||
2768 | * @param int $status - default 0 - pending |
||
2769 | * @param int $payoutId - for get an individual payout if want all then false |
||
2770 | * |
||
2771 | * @return array |
||
2772 | */ |
||
2773 | public function getPayouts( |
||
2774 | int $status = self::PAYOUT_STATUS_PENDING, |
||
2775 | int $payoutId = 0, |
||
2776 | int $userId = 0 |
||
2777 | ) { |
||
2778 | $condition = ($payoutId) ? 'AND p.id = '.($payoutId) : ''; |
||
2779 | $condition2 = ($userId) ? ' AND p.user_id = '.($userId) : ''; |
||
2780 | $typeResult = ($condition) ? 'first' : 'all'; |
||
2781 | $payoutsTable = Database::get_main_table(self::TABLE_PAYPAL_PAYOUTS); |
||
2782 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
2783 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
2784 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
2785 | $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD); |
||
2786 | $extraFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES); |
||
2787 | |||
2788 | $paypalExtraField = Database::select( |
||
2789 | "*", |
||
2790 | $extraFieldTable, |
||
2791 | [ |
||
2792 | 'where' => ['variable = ?' => 'paypal'], |
||
2793 | ], |
||
2794 | 'first' |
||
2795 | ); |
||
2796 | |||
2797 | if (!$paypalExtraField) { |
||
2798 | return false; |
||
2799 | } |
||
2800 | |||
2801 | $innerJoins = " |
||
2802 | INNER JOIN $userTable u ON p.user_id = u.id |
||
2803 | INNER JOIN $saleTable s ON s.id = p.sale_id |
||
2804 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
2805 | LEFT JOIN $extraFieldValues efv ON p.user_id = efv.item_id |
||
2806 | AND field_id = ".((int) $paypalExtraField['id'])." |
||
2807 | "; |
||
2808 | |||
2809 | $payouts = Database::select( |
||
2810 | "p.* , u.firstname, u.lastname, efv.value as paypal_account, s.reference as sale_reference, s.price as item_price, c.iso_code", |
||
2811 | "$payoutsTable p $innerJoins", |
||
2812 | [ |
||
2813 | 'where' => ['p.status = ? '.$condition.' '.$condition2 => $status], |
||
2814 | ], |
||
2815 | $typeResult |
||
2816 | ); |
||
2817 | |||
2818 | return $payouts; |
||
2819 | } |
||
2820 | |||
2821 | /** |
||
2822 | * Verify if the beneficiary have a paypal account. |
||
2823 | * |
||
2824 | * @return true if the user have a paypal account, false if not |
||
2825 | */ |
||
2826 | public function verifyPaypalAccountByBeneficiary(int $userId) |
||
2827 | { |
||
2828 | $extraFieldTable = Database::get_main_table(TABLE_EXTRA_FIELD); |
||
2829 | $extraFieldValues = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES); |
||
2830 | |||
2831 | $paypalExtraField = Database::select( |
||
2832 | '*', |
||
2833 | $extraFieldTable, |
||
2834 | [ |
||
2835 | 'where' => ['variable = ?' => 'paypal'], |
||
2836 | ], |
||
2837 | 'first' |
||
2838 | ); |
||
2839 | |||
2840 | if (!$paypalExtraField) { |
||
2841 | return false; |
||
2842 | } |
||
2843 | |||
2844 | $paypalFieldId = $paypalExtraField['id']; |
||
2845 | $paypalAccount = Database::select( |
||
2846 | 'value', |
||
2847 | $extraFieldValues, |
||
2848 | [ |
||
2849 | 'where' => ['field_id = ? AND item_id = ?' => [(int) $paypalFieldId, $userId]], |
||
2850 | ], |
||
2851 | 'first' |
||
2852 | ); |
||
2853 | |||
2854 | if (!$paypalAccount) { |
||
2855 | return false; |
||
2856 | } |
||
2857 | |||
2858 | if ($paypalAccount['value'] === '') { |
||
2859 | return false; |
||
2860 | } |
||
2861 | |||
2862 | return true; |
||
2863 | } |
||
2864 | |||
2865 | /** |
||
2866 | * Register the users payouts. |
||
2867 | * |
||
2868 | * @return array |
||
2869 | */ |
||
2870 | public function storePayouts(int $saleId) |
||
2871 | { |
||
2872 | $payoutsTable = Database::get_main_table(self::TABLE_PAYPAL_PAYOUTS); |
||
2873 | $platformCommission = $this->getPlatformCommission(); |
||
2874 | |||
2875 | $sale = $this->getSale($saleId); |
||
2876 | $commission = (int) $platformCommission['commission']; |
||
2877 | $teachersCommission = number_format( |
||
2878 | (floatval($sale['price']) * $commission) / 100, |
||
2879 | 2 |
||
2880 | ); |
||
2881 | |||
2882 | $beneficiaries = $this->getBeneficiariesBySale($saleId); |
||
2883 | foreach ($beneficiaries as $beneficiary) { |
||
2884 | $beneficiaryCommission = (int) $beneficiary['commissions']; |
||
2885 | Database::insert( |
||
2886 | $payoutsTable, |
||
2887 | [ |
||
2888 | 'date' => $sale['date'], |
||
2889 | 'payout_date' => api_get_utc_datetime(), |
||
2890 | 'sale_id' => $saleId, |
||
2891 | 'user_id' => $beneficiary['user_id'], |
||
2892 | 'commission' => number_format( |
||
2893 | (floatval($teachersCommission) * $beneficiaryCommission) / 100, |
||
2894 | 2 |
||
2895 | ), |
||
2896 | 'status' => self::PAYOUT_STATUS_PENDING, |
||
2897 | ] |
||
2898 | ); |
||
2899 | } |
||
2900 | } |
||
2901 | |||
2902 | /** |
||
2903 | * Register the users payouts. |
||
2904 | * |
||
2905 | * @param int $saleId The subscription sale ID |
||
2906 | * |
||
2907 | * @return array |
||
2908 | */ |
||
2909 | public function storeSubscriptionPayouts(int $saleId) |
||
2910 | { |
||
2911 | $payoutsTable = Database::get_main_table(self::TABLE_PAYPAL_PAYOUTS); |
||
2912 | $platformCommission = $this->getPlatformCommission(); |
||
2913 | |||
2914 | $sale = $this->getSubscriptionSale($saleId); |
||
2915 | $commission = (int) $platformCommission['commission']; |
||
2916 | $teachersCommission = number_format( |
||
2917 | (floatval($sale['price']) * $commission) / 100, |
||
2918 | 2 |
||
2919 | ); |
||
2920 | |||
2921 | $beneficiaries = $this->getBeneficiariesBySale($saleId); |
||
2922 | foreach ($beneficiaries as $beneficiary) { |
||
2923 | $beneficiaryCommission = (int) $beneficiary['commissions']; |
||
2924 | Database::insert( |
||
2925 | $payoutsTable, |
||
2926 | [ |
||
2927 | 'date' => $sale['date'], |
||
2928 | 'payout_date' => api_get_utc_datetime(), |
||
2929 | 'sale_id' => $saleId, |
||
2930 | 'user_id' => $beneficiary['user_id'], |
||
2931 | 'commission' => number_format( |
||
2932 | (floatval($teachersCommission) * $beneficiaryCommission) / 100, |
||
2933 | 2 |
||
2934 | ), |
||
2935 | 'status' => self::PAYOUT_STATUS_PENDING, |
||
2936 | ] |
||
2937 | ); |
||
2938 | } |
||
2939 | } |
||
2940 | |||
2941 | /** |
||
2942 | * Register the users payouts. |
||
2943 | * |
||
2944 | * @param int $payoutId The payout ID |
||
2945 | * @param int $status The status to set (-1 to cancel, 0 to pending, 1 to completed) |
||
2946 | * |
||
2947 | * @return array |
||
2948 | */ |
||
2949 | public function setStatusPayouts(int $payoutId, int $status) |
||
2950 | { |
||
2951 | $payoutsTable = Database::get_main_table(self::TABLE_PAYPAL_PAYOUTS); |
||
2952 | |||
2953 | Database::update( |
||
2954 | $payoutsTable, |
||
2955 | ['status' => (int) $status], |
||
2956 | ['id = ?' => (int) $payoutId] |
||
2957 | ); |
||
2958 | } |
||
2959 | |||
2960 | /** |
||
2961 | * Gets the stored platform commission params. |
||
2962 | * |
||
2963 | * @return array |
||
2964 | */ |
||
2965 | public function getPlatformCommission() |
||
2966 | { |
||
2967 | return Database::select( |
||
2968 | '*', |
||
2969 | Database::get_main_table(self::TABLE_COMMISSION), |
||
2970 | ['id = ?' => 1], |
||
2971 | 'first' |
||
2972 | ); |
||
2973 | } |
||
2974 | |||
2975 | /** |
||
2976 | * Update the platform commission. |
||
2977 | * |
||
2978 | * @param array $params platform commission |
||
2979 | * |
||
2980 | * @return int The number of affected rows. Otherwise return false |
||
2981 | */ |
||
2982 | public function updateCommission(array $params) |
||
2983 | { |
||
2984 | $commissionTable = Database::get_main_table(self::TABLE_COMMISSION); |
||
2985 | |||
2986 | return Database::update( |
||
2987 | $commissionTable, |
||
2988 | ['commission' => (int) $params['commission']] |
||
2989 | ); |
||
2990 | } |
||
2991 | |||
2992 | /** |
||
2993 | * Register additional service. |
||
2994 | * |
||
2995 | * @param array $service params |
||
2996 | * |
||
2997 | * @return mixed response |
||
2998 | */ |
||
2999 | public function storeService(array $service) |
||
3000 | { |
||
3001 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3002 | |||
3003 | $return = Database::insert( |
||
3004 | $servicesTable, |
||
3005 | [ |
||
3006 | 'name' => Security::remove_XSS($service['name']), |
||
3007 | 'description' => Security::remove_XSS($service['description']), |
||
3008 | 'price' => $service['price'], |
||
3009 | 'tax_perc' => $service['tax_perc'] != '' ? (int) $service['tax_perc'] : null, |
||
3010 | 'duration_days' => (int) $service['duration_days'], |
||
3011 | 'applies_to' => (int) $service['applies_to'], |
||
3012 | 'owner_id' => (int) $service['owner_id'], |
||
3013 | 'visibility' => (int) $service['visibility'], |
||
3014 | 'image' => '', |
||
3015 | 'video_url' => $service['video_url'], |
||
3016 | 'service_information' => $service['service_information'], |
||
3017 | ] |
||
3018 | ); |
||
3019 | |||
3020 | if ($return && !empty($service['picture_crop_image_base_64']) && |
||
3021 | !empty($service['picture_crop_result']) |
||
3022 | ) { |
||
3023 | $img = str_replace('data:image/png;base64,', '', $service['picture_crop_image_base_64']); |
||
3024 | $img = str_replace(' ', '+', $img); |
||
3025 | $data = base64_decode($img); |
||
3026 | $file = api_get_path(SYS_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$return.'.png'; |
||
3027 | file_put_contents($file, $data); |
||
3028 | |||
3029 | Database::update( |
||
3030 | $servicesTable, |
||
3031 | ['image' => 'simg-'.$return.'.png'], |
||
3032 | ['id = ?' => $return] |
||
3033 | ); |
||
3034 | } |
||
3035 | |||
3036 | return $return; |
||
3037 | } |
||
3038 | |||
3039 | /** |
||
3040 | * update a service. |
||
3041 | * |
||
3042 | * @return mixed response |
||
3043 | */ |
||
3044 | public function updateService(array $service, int $id) |
||
3045 | { |
||
3046 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3047 | if (!empty($service['picture_crop_image_base_64'])) { |
||
3048 | $img = str_replace('data:image/png;base64,', '', $service['picture_crop_image_base_64']); |
||
3049 | $img = str_replace(' ', '+', $img); |
||
3050 | $data = base64_decode($img); |
||
3051 | $file = api_get_path(SYS_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$id.'.png'; |
||
3052 | file_put_contents($file, $data); |
||
3053 | } |
||
3054 | |||
3055 | return Database::update( |
||
3056 | $servicesTable, |
||
3057 | [ |
||
3058 | 'name' => Security::remove_XSS($service['name']), |
||
3059 | 'description' => Security::remove_XSS($service['description']), |
||
3060 | 'price' => $service['price'], |
||
3061 | 'tax_perc' => $service['tax_perc'] != '' ? (int) $service['tax_perc'] : null, |
||
3062 | 'duration_days' => (int) $service['duration_days'], |
||
3063 | 'applies_to' => (int) $service['applies_to'], |
||
3064 | 'owner_id' => (int) $service['owner_id'], |
||
3065 | 'visibility' => (int) $service['visibility'], |
||
3066 | 'image' => 'simg-'.$id.'.png', |
||
3067 | 'video_url' => $service['video_url'], |
||
3068 | 'service_information' => $service['service_information'], |
||
3069 | ], |
||
3070 | ['id = ?' => $id] |
||
3071 | ); |
||
3072 | } |
||
3073 | |||
3074 | /** |
||
3075 | * Remove a service. |
||
3076 | * |
||
3077 | * @param int $id The transfer account ID |
||
3078 | * |
||
3079 | * @return int Rows affected. Otherwise return false |
||
3080 | */ |
||
3081 | public function deleteService(int $id) |
||
3082 | { |
||
3083 | Database::delete( |
||
3084 | Database::get_main_table(self::TABLE_SERVICES_SALE), |
||
3085 | ['service_id = ?' => $id] |
||
3086 | ); |
||
3087 | |||
3088 | return Database::delete( |
||
3089 | Database::get_main_table(self::TABLE_SERVICES), |
||
3090 | ['id = ?' => $id] |
||
3091 | ); |
||
3092 | } |
||
3093 | |||
3094 | /** |
||
3095 | * @param array|null $coupon Array with at least 'discount_type' and 'discount_amount' elements |
||
3096 | */ |
||
3097 | public function setPriceSettings(array &$product, int $productType, array $coupon = null): bool |
||
3098 | { |
||
3099 | if (empty($product)) { |
||
3100 | return false; |
||
3101 | } |
||
3102 | |||
3103 | $taxPerc = null; |
||
3104 | $product['has_coupon'] = $coupon != null ? true : false; |
||
3105 | $couponDiscount = 0; |
||
3106 | if ($coupon != null) { |
||
3107 | if ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_AMOUNT) { |
||
3108 | $couponDiscount = $coupon['discount_amount']; |
||
3109 | } elseif ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_PERCENTAGE) { |
||
3110 | $couponDiscount = ($product['price'] * $coupon['discount_amount']) / 100; |
||
3111 | } |
||
3112 | $product['price_without_discount'] = $product['price']; |
||
3113 | } |
||
3114 | $product['discount_amount'] = $couponDiscount; |
||
3115 | $product['price'] = $product['price'] - $couponDiscount; |
||
3116 | $priceWithoutTax = $product['price']; |
||
3117 | $product['total_price'] = $product['price']; |
||
3118 | $product['tax_amount'] = 0; |
||
3119 | |||
3120 | if ($this->checkTaxEnabledInProduct($productType)) { |
||
3121 | if (is_null($product['tax_perc'])) { |
||
3122 | $globalParameters = $this->getGlobalParameters(); |
||
3123 | $globalTaxPerc = $globalParameters['global_tax_perc']; |
||
3124 | $taxPerc = $globalTaxPerc; |
||
3125 | } else { |
||
3126 | $taxPerc = $product['tax_perc']; |
||
3127 | } |
||
3128 | //$taxPerc = is_null($product['tax_perc']) ? $globalTaxPerc : $product['tax_perc']; |
||
3129 | |||
3130 | $taxAmount = round($priceWithoutTax * $taxPerc / 100, 2); |
||
3131 | $product['tax_amount'] = $taxAmount; |
||
3132 | $priceWithTax = $priceWithoutTax + $taxAmount; |
||
3133 | $product['total_price'] = $priceWithTax; |
||
3134 | } |
||
3135 | |||
3136 | $product['tax_perc_show'] = $taxPerc; |
||
3137 | $product['price_formatted'] = $this->getPriceWithCurrencyFromIsoCode( |
||
3138 | $product['price'], |
||
3139 | $product['iso_code'] |
||
3140 | ); |
||
3141 | |||
3142 | $product['tax_amount_formatted'] = number_format($product['tax_amount'], 2); |
||
3143 | |||
3144 | $product['total_price_formatted'] = $this->getPriceWithCurrencyFromIsoCode( |
||
3145 | $product['total_price'], |
||
3146 | $product['iso_code'] |
||
3147 | ); |
||
3148 | |||
3149 | if ($coupon != null) { |
||
3150 | $product['discount_amount_formatted'] = $this->getPriceWithCurrencyFromIsoCode( |
||
3151 | $product['discount_amount'], |
||
3152 | $product['iso_code'] |
||
3153 | ); |
||
3154 | |||
3155 | $product['price_without_discount_formatted'] = $this->getPriceWithCurrencyFromIsoCode( |
||
3156 | $product['price_without_discount'], |
||
3157 | $product['iso_code'] |
||
3158 | ); |
||
3159 | } |
||
3160 | |||
3161 | return true; |
||
3162 | } |
||
3163 | |||
3164 | /** |
||
3165 | * @param array $coupon |
||
3166 | * |
||
3167 | * @return array |
||
3168 | */ |
||
3169 | public function getService(int $id, array $coupon = null) |
||
3170 | { |
||
3171 | if (empty($id)) { |
||
3172 | return []; |
||
3173 | } |
||
3174 | |||
3175 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3176 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
3177 | $conditions = ['WHERE' => ['s.id = ?' => $id]]; |
||
3178 | $showData = 'first'; |
||
3179 | $innerJoins = "INNER JOIN $userTable u ON s.owner_id = u.id"; |
||
3180 | $currency = $this->getSelectedCurrency(); |
||
3181 | $isoCode = $currency['iso_code']; |
||
3182 | $service = Database::select( |
||
3183 | "s.*, '$isoCode' as currency, u.firstname, u.lastname", |
||
3184 | "$servicesTable s $innerJoins", |
||
3185 | $conditions, |
||
3186 | $showData |
||
3187 | ); |
||
3188 | |||
3189 | $service['iso_code'] = $isoCode; |
||
3190 | $globalParameters = $this->getGlobalParameters(); |
||
3191 | |||
3192 | $this->setPriceSettings($service, self::TAX_APPLIES_TO_ONLY_SERVICES, $coupon); |
||
3193 | |||
3194 | $service['tax_name'] = $globalParameters['tax_name']; |
||
3195 | $service['tax_enable'] = $this->checkTaxEnabledInProduct(self::TAX_APPLIES_TO_ONLY_SERVICES); |
||
3196 | $service['owner_name'] = api_get_person_name($service['firstname'], $service['lastname']); |
||
3197 | $service['image'] = !empty($service['image']) ? api_get_path(WEB_PLUGIN_PATH).'buycourses/uploads/services/images/'.$service['image'] : null; |
||
3198 | |||
3199 | return $service; |
||
3200 | } |
||
3201 | |||
3202 | /** |
||
3203 | * List additional services. |
||
3204 | * |
||
3205 | * @return array |
||
3206 | */ |
||
3207 | public function getAllServices() |
||
3208 | { |
||
3209 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3210 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
3211 | |||
3212 | $innerJoins = "INNER JOIN $userTable u ON s.owner_id = u.id"; |
||
3213 | $return = Database::select( |
||
3214 | 's.id', |
||
3215 | "$servicesTable s $innerJoins", |
||
3216 | [], |
||
3217 | 'all' |
||
3218 | ); |
||
3219 | |||
3220 | $services = []; |
||
3221 | foreach ($return as $index => $service) { |
||
3222 | $services[$index] = $this->getService($service['id']); |
||
3223 | } |
||
3224 | |||
3225 | return $services; |
||
3226 | } |
||
3227 | |||
3228 | /** |
||
3229 | * List additional services. |
||
3230 | * |
||
3231 | * @return array|int |
||
3232 | */ |
||
3233 | public function getServices(int $start, int $end, string $typeResult = 'all') |
||
3234 | { |
||
3235 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3236 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
3237 | |||
3238 | $conditions = ['limit' => "$start, $end"]; |
||
3239 | $innerJoins = "INNER JOIN $userTable u ON s.owner_id = u.id"; |
||
3240 | $return = Database::select( |
||
3241 | 's.id', |
||
3242 | "$servicesTable s $innerJoins", |
||
3243 | $conditions, |
||
3244 | $typeResult |
||
3245 | ); |
||
3246 | |||
3247 | if ($typeResult === 'count') { |
||
3248 | return $return; |
||
3249 | } |
||
3250 | |||
3251 | $services = []; |
||
3252 | foreach ($return as $index => $service) { |
||
3253 | $services[$index] = $this->getService($service['id']); |
||
3254 | } |
||
3255 | |||
3256 | return $services; |
||
3257 | } |
||
3258 | |||
3259 | /** |
||
3260 | * Get the statuses for sales. |
||
3261 | * |
||
3262 | * @return array |
||
3263 | */ |
||
3264 | public function getServiceSaleStatuses() |
||
3265 | { |
||
3266 | return [ |
||
3267 | self::SERVICE_STATUS_CANCELLED => $this->get_lang('SaleStatusCancelled'), |
||
3268 | self::SERVICE_STATUS_PENDING => $this->get_lang('SaleStatusPending'), |
||
3269 | self::SERVICE_STATUS_COMPLETED => $this->get_lang('SaleStatusCompleted'), |
||
3270 | ]; |
||
3271 | } |
||
3272 | |||
3273 | /** |
||
3274 | * List services sales. |
||
3275 | * |
||
3276 | * @param int $buyerId buyer id |
||
3277 | * @param int $status status |
||
3278 | * @param int $nodeType The node Type ( User = 1 , Course = 2 , Session = 3 ) |
||
3279 | * @param int $nodeId the nodeId |
||
3280 | * |
||
3281 | * @return array |
||
3282 | */ |
||
3283 | public function getServiceSales( |
||
3284 | int $buyerId = 0, |
||
3285 | int $status = 0, |
||
3286 | int $nodeType = 0, |
||
3287 | int $nodeId = 0 |
||
3288 | ) { |
||
3289 | $conditions = null; |
||
3290 | $groupBy = ''; |
||
3291 | |||
3292 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3293 | $servicesSaleTable = Database::get_main_table(self::TABLE_SERVICES_SALE); |
||
3294 | |||
3295 | $defaultOrder = 'id ASC'; |
||
3296 | |||
3297 | if (!empty($buyerId)) { |
||
3298 | $conditions = ['WHERE' => ['ss.buyer_id = ?' => $buyerId], 'ORDER' => $defaultOrder]; |
||
3299 | } |
||
3300 | |||
3301 | if (is_numeric($status)) { |
||
3302 | $conditions = ['WHERE' => ['ss.status = ?' => $status], 'ORDER' => $defaultOrder]; |
||
3303 | } |
||
3304 | |||
3305 | if ($buyerId) { |
||
3306 | $conditions = ['WHERE' => ['ss.buyer_id = ?' => [$buyerId]], 'ORDER' => $defaultOrder]; |
||
3307 | } |
||
3308 | |||
3309 | if ($nodeType && $nodeId) { |
||
3310 | $conditions = [ |
||
3311 | 'WHERE' => ['ss.node_type = ? AND ss.node_id = ?' => [$nodeType, $nodeId]], |
||
3312 | 'ORDER' => $defaultOrder, |
||
3313 | ]; |
||
3314 | } |
||
3315 | |||
3316 | if ($nodeType && $nodeId && $buyerId && is_numeric($status)) { |
||
3317 | $conditions = [ |
||
3318 | 'WHERE' => [ |
||
3319 | 'ss.node_type = ? AND ss.node_id = ? AND ss.buyer_id = ? AND ss.status = ?' => [ |
||
3320 | $nodeType, |
||
3321 | $nodeId, |
||
3322 | $buyerId, |
||
3323 | $status, |
||
3324 | ], |
||
3325 | ], |
||
3326 | 'ORDER' => 'ss.service_id ASC', |
||
3327 | ]; |
||
3328 | } |
||
3329 | |||
3330 | $innerJoins = "INNER JOIN $servicesTable s ON ss.service_id = s.id $groupBy"; |
||
3331 | $return = Database::select( |
||
3332 | 'DISTINCT ss.id ', |
||
3333 | "$servicesSaleTable ss $innerJoins", |
||
3334 | $conditions |
||
3335 | //, "all", null, true |
||
3336 | ); |
||
3337 | |||
3338 | $list = []; |
||
3339 | foreach ($return as $service) { |
||
3340 | $list[] = $this->getServiceSale($service['id']); |
||
3341 | } |
||
3342 | |||
3343 | return $list; |
||
3344 | } |
||
3345 | |||
3346 | /** |
||
3347 | * @param int $id service sale id |
||
3348 | * |
||
3349 | * @return array |
||
3350 | */ |
||
3351 | public function getServiceSale(int $id) |
||
3352 | { |
||
3353 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3354 | $servicesSaleTable = Database::get_main_table(self::TABLE_SERVICES_SALE); |
||
3355 | |||
3356 | if (empty($id)) { |
||
3357 | return []; |
||
3358 | } |
||
3359 | |||
3360 | $conditions = ['WHERE' => ['ss.id = ?' => $id]]; |
||
3361 | $innerJoins = "INNER JOIN $servicesTable s ON ss.service_id = s.id "; |
||
3362 | $currency = $this->getSelectedCurrency(); |
||
3363 | $isoCode = $currency['iso_code']; |
||
3364 | |||
3365 | $servicesSale = Database::select( |
||
3366 | 'ss.*, s.name, s.description, s.price as service_price, s.duration_days, s.applies_to, s.owner_id, s.visibility, s.image', |
||
3367 | "$servicesSaleTable ss $innerJoins", |
||
3368 | $conditions, |
||
3369 | 'first' |
||
3370 | ); |
||
3371 | $owner = api_get_user_info($servicesSale['owner_id']); |
||
3372 | $buyer = api_get_user_info($servicesSale['buyer_id']); |
||
3373 | |||
3374 | $servicesSale['service']['id'] = $servicesSale['service_id']; |
||
3375 | $servicesSale['service']['name'] = $servicesSale['name']; |
||
3376 | $servicesSale['service']['description'] = $servicesSale['description']; |
||
3377 | $servicesSale['service']['price'] = $servicesSale['service_price']; |
||
3378 | $servicesSale['service']['currency'] = $isoCode; |
||
3379 | |||
3380 | $servicesSale['service']['total_price'] = $this->getPriceWithCurrencyFromIsoCode( |
||
3381 | $servicesSale['price'], |
||
3382 | $isoCode |
||
3383 | ); |
||
3384 | |||
3385 | $servicesSale['service']['duration_days'] = $servicesSale['duration_days']; |
||
3386 | $servicesSale['service']['applies_to'] = $servicesSale['applies_to']; |
||
3387 | $servicesSale['service']['owner']['id'] = $servicesSale['owner_id']; |
||
3388 | $servicesSale['service']['owner']['name'] = api_get_person_name($owner['firstname'], $owner['lastname']); |
||
3389 | $servicesSale['service']['visibility'] = $servicesSale['visibility']; |
||
3390 | $servicesSale['service']['image'] = $servicesSale['image']; |
||
3391 | $servicesSale['item'] = $this->getService($servicesSale['service_id']); |
||
3392 | $servicesSale['buyer']['id'] = $buyer['user_id']; |
||
3393 | $servicesSale['buyer']['name'] = api_get_person_name($buyer['firstname'], $buyer['lastname']); |
||
3394 | $servicesSale['buyer']['username'] = $buyer['username']; |
||
3395 | |||
3396 | return $servicesSale; |
||
3397 | } |
||
3398 | |||
3399 | /** |
||
3400 | * Update service sale status to cancelled. |
||
3401 | * |
||
3402 | * @param int $serviceSaleId The sale ID |
||
3403 | * |
||
3404 | * @return bool |
||
3405 | */ |
||
3406 | public function cancelServiceSale(int $serviceSaleId) |
||
3407 | { |
||
3408 | $this->updateServiceSaleStatus( |
||
3409 | $serviceSaleId, |
||
3410 | self::SERVICE_STATUS_CANCELLED |
||
3411 | ); |
||
3412 | |||
3413 | return true; |
||
3414 | } |
||
3415 | |||
3416 | /** |
||
3417 | * Complete service sale process. Update service sale status to completed. |
||
3418 | * |
||
3419 | * @param int $serviceSaleId The service sale ID |
||
3420 | * |
||
3421 | * @return bool |
||
3422 | */ |
||
3423 | public function completeServiceSale(int $serviceSaleId) |
||
3424 | { |
||
3425 | $serviceSale = $this->getServiceSale($serviceSaleId); |
||
3426 | if ($serviceSale['status'] == self::SERVICE_STATUS_COMPLETED) { |
||
3427 | return true; |
||
3428 | } |
||
3429 | |||
3430 | $this->updateServiceSaleStatus( |
||
3431 | $serviceSaleId, |
||
3432 | self::SERVICE_STATUS_COMPLETED |
||
3433 | ); |
||
3434 | |||
3435 | if ($this->get('invoicing_enable') === 'true') { |
||
3436 | $this->setInvoice($serviceSaleId, 1); |
||
3437 | } |
||
3438 | |||
3439 | return true; |
||
3440 | } |
||
3441 | |||
3442 | /** |
||
3443 | * Lists current service details. |
||
3444 | * |
||
3445 | * @return array|int |
||
3446 | */ |
||
3447 | public function getCatalogServiceList( |
||
3448 | int $start, |
||
3449 | int $end, |
||
3450 | string $name = null, |
||
3451 | int $min = 0, |
||
3452 | int $max = 0, |
||
3453 | $appliesTo = '', |
||
3454 | string $typeResult = 'all' |
||
3455 | ) { |
||
3456 | $servicesTable = Database::get_main_table(self::TABLE_SERVICES); |
||
3457 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
3458 | |||
3459 | $whereConditions = [ |
||
3460 | 's.visibility <> ? ' => 0, |
||
3461 | ]; |
||
3462 | |||
3463 | if (!empty($name)) { |
||
3464 | $whereConditions['AND s.name LIKE %?%'] = $name; |
||
3465 | } |
||
3466 | |||
3467 | if (!empty($min)) { |
||
3468 | $whereConditions['AND s.price >= ?'] = $min; |
||
3469 | } |
||
3470 | |||
3471 | if (!empty($max)) { |
||
3472 | $whereConditions['AND s.price <= ?'] = $max; |
||
3473 | } |
||
3474 | |||
3475 | if (!$appliesTo == '') { |
||
3476 | $whereConditions['AND s.applies_to = ?'] = $appliesTo; |
||
3477 | } |
||
3478 | |||
3479 | $innerJoins = "INNER JOIN $userTable u ON s.owner_id = u.id"; |
||
3480 | $return = Database::select( |
||
3481 | 's.*', |
||
3482 | "$servicesTable s $innerJoins", |
||
3483 | ['WHERE' => $whereConditions, 'limit' => "$start, $end"], |
||
3484 | $typeResult |
||
3485 | ); |
||
3486 | |||
3487 | if ($typeResult === 'count') { |
||
3488 | return $return; |
||
3489 | } |
||
3490 | |||
3491 | $services = []; |
||
3492 | foreach ($return as $index => $service) { |
||
3493 | $services[$index] = $this->getService($service['id']); |
||
3494 | } |
||
3495 | |||
3496 | return $services; |
||
3497 | } |
||
3498 | |||
3499 | /** |
||
3500 | * Register a Service sale. |
||
3501 | * |
||
3502 | * @param int $serviceId The service ID |
||
3503 | * @param int $paymentType The payment type |
||
3504 | * @param int $infoSelect The ID for Service Type |
||
3505 | * |
||
3506 | * @return bool |
||
3507 | */ |
||
3508 | public function registerServiceSale(int $serviceId, int $paymentType, int $infoSelect, int $couponId = null) |
||
3509 | { |
||
3510 | if (!in_array( |
||
3511 | $paymentType, |
||
3512 | [self::PAYMENT_TYPE_PAYPAL, self::PAYMENT_TYPE_TRANSFER, self::PAYMENT_TYPE_CULQI] |
||
3513 | ) |
||
3514 | ) { |
||
3515 | return false; |
||
3516 | } |
||
3517 | |||
3518 | $userId = api_get_user_id(); |
||
3519 | $service = $this->getService($serviceId); |
||
3520 | |||
3521 | if (empty($service)) { |
||
3522 | return false; |
||
3523 | } |
||
3524 | |||
3525 | if ($couponId != null) { |
||
3526 | $coupon = $this->getCouponService($couponId, $serviceId); |
||
3527 | } |
||
3528 | |||
3529 | $couponDiscount = 0; |
||
3530 | $priceWithoutDiscount = 0; |
||
3531 | if ($coupon != null) { |
||
3532 | if ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_AMOUNT) { |
||
3533 | $couponDiscount = $coupon['discount_amount']; |
||
3534 | } elseif ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_PERCENTAGE) { |
||
3535 | $couponDiscount = ($service['price'] * $coupon['discount_amount']) / 100; |
||
3536 | } |
||
3537 | $priceWithoutDiscount = $service['price']; |
||
3538 | } |
||
3539 | $service['price'] = $service['price'] - $couponDiscount; |
||
3540 | $currency = $this->getSelectedCurrency(); |
||
3541 | $price = $service['price']; |
||
3542 | $priceWithoutTax = null; |
||
3543 | $taxPerc = null; |
||
3544 | $taxEnable = $this->get('tax_enable') === 'true'; |
||
3545 | $globalParameters = $this->getGlobalParameters(); |
||
3546 | $taxAppliesTo = $globalParameters['tax_applies_to']; |
||
3547 | $taxAmount = 0; |
||
3548 | |||
3549 | if ($taxEnable && |
||
3550 | ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SERVICES) |
||
3551 | ) { |
||
3552 | $priceWithoutTax = $service['price']; |
||
3553 | $globalTaxPerc = $globalParameters['global_tax_perc']; |
||
3554 | $precision = 2; |
||
3555 | $taxPerc = is_null($service['tax_perc']) ? $globalTaxPerc : $service['tax_perc']; |
||
3556 | $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); |
||
3557 | $price = $priceWithoutTax + $taxAmount; |
||
3558 | } |
||
3559 | |||
3560 | $values = [ |
||
3561 | 'service_id' => $serviceId, |
||
3562 | 'reference' => $this->generateReference( |
||
3563 | $userId, |
||
3564 | $service['applies_to'], |
||
3565 | $infoSelect |
||
3566 | ), |
||
3567 | 'currency_id' => $currency['id'], |
||
3568 | 'price' => $price, |
||
3569 | 'price_without_tax' => $priceWithoutTax, |
||
3570 | 'tax_perc' => $taxPerc, |
||
3571 | 'tax_amount' => $taxAmount, |
||
3572 | 'node_type' => $service['applies_to'], |
||
3573 | 'node_id' => $infoSelect, |
||
3574 | 'buyer_id' => $userId, |
||
3575 | 'buy_date' => api_get_utc_datetime(), |
||
3576 | 'date_start' => api_get_utc_datetime(), |
||
3577 | 'date_end' => date_format( |
||
3578 | date_add( |
||
3579 | date_create(api_get_utc_datetime()), |
||
3580 | date_interval_create_from_date_string($service['duration_days'].' days') |
||
3581 | ), |
||
3582 | 'Y-m-d H:i:s' |
||
3583 | ), |
||
3584 | 'status' => self::SERVICE_STATUS_PENDING, |
||
3585 | 'payment_type' => $paymentType, |
||
3586 | 'price_without_discount' => $priceWithoutDiscount, |
||
3587 | 'discount_amount' => $couponDiscount, |
||
3588 | ]; |
||
3589 | |||
3590 | $returnedServiceSaleId = Database::insert(self::TABLE_SERVICES_SALE, $values); |
||
3591 | |||
3592 | return $returnedServiceSaleId; |
||
3593 | } |
||
3594 | |||
3595 | /** |
||
3596 | * Save Culqi configuration params. |
||
3597 | * |
||
3598 | * @return int Rows affected. Otherwise return false |
||
3599 | */ |
||
3600 | public function saveCulqiParameters(array $params) |
||
3601 | { |
||
3602 | return Database::update( |
||
3603 | Database::get_main_table(self::TABLE_CULQI), |
||
3604 | [ |
||
3605 | 'commerce_code' => $params['commerce_code'], |
||
3606 | 'api_key' => $params['api_key'], |
||
3607 | 'integration' => $params['integration'], |
||
3608 | ], |
||
3609 | ['id = ?' => 1] |
||
3610 | ); |
||
3611 | } |
||
3612 | |||
3613 | /** |
||
3614 | * Gets the stored Culqi params. |
||
3615 | * |
||
3616 | * @return array |
||
3617 | */ |
||
3618 | public function getCulqiParams() |
||
3619 | { |
||
3620 | return Database::select( |
||
3621 | '*', |
||
3622 | Database::get_main_table(self::TABLE_CULQI), |
||
3623 | ['id = ?' => 1], |
||
3624 | 'first' |
||
3625 | ); |
||
3626 | } |
||
3627 | |||
3628 | /** |
||
3629 | * Save Cecabank configuration params. |
||
3630 | * |
||
3631 | * @return array |
||
3632 | */ |
||
3633 | public function saveCecabankParameters(array $params) |
||
3634 | { |
||
3635 | return Database::update( |
||
3636 | Database::get_main_table(self::TABLE_TPV_CECABANK), |
||
3637 | [ |
||
3638 | 'crypto_key' => $params['crypto_key'], |
||
3639 | 'merchant_id' => $params['merchart_id'], |
||
3640 | 'acquirer_bin' => $params['acquirer_bin'], |
||
3641 | 'terminal_id' => $params['terminal_id'], |
||
3642 | 'cypher' => $params['cypher'], |
||
3643 | 'exponent' => $params['exponent'], |
||
3644 | 'supported_payment' => $params['supported_payment'], |
||
3645 | 'url' => $params['url'], |
||
3646 | ], |
||
3647 | ['id = ?' => 1] |
||
3648 | ); |
||
3649 | } |
||
3650 | |||
3651 | /** |
||
3652 | * Gets the stored Cecabank params. |
||
3653 | * |
||
3654 | * @return array |
||
3655 | */ |
||
3656 | public function getCecabankParams() |
||
3657 | { |
||
3658 | return Database::select( |
||
3659 | '*', |
||
3660 | Database::get_main_table(self::TABLE_TPV_CECABANK), |
||
3661 | ['id = ?' => 1], |
||
3662 | 'first' |
||
3663 | ); |
||
3664 | } |
||
3665 | |||
3666 | /** |
||
3667 | * Save Global Parameters. |
||
3668 | * |
||
3669 | * @return int Rows affected. Otherwise return false |
||
3670 | */ |
||
3671 | public function saveGlobalParameters(array $params) |
||
3672 | { |
||
3673 | $sqlParams = [ |
||
3674 | 'terms_and_conditions' => $params['terms_and_conditions'], |
||
3675 | 'sale_email' => $params['sale_email'], |
||
3676 | ]; |
||
3677 | |||
3678 | if ($this->get('tax_enable') === 'true') { |
||
3679 | $sqlParams['global_tax_perc'] = $params['global_tax_perc']; |
||
3680 | $sqlParams['tax_applies_to'] = $params['tax_applies_to']; |
||
3681 | $sqlParams['tax_name'] = $params['tax_name']; |
||
3682 | } |
||
3683 | |||
3684 | if ($this->get('invoicing_enable') === 'true') { |
||
3685 | $sqlParams['seller_name'] = $params['seller_name']; |
||
3686 | $sqlParams['seller_id'] = $params['seller_id']; |
||
3687 | $sqlParams['seller_address'] = $params['seller_address']; |
||
3688 | $sqlParams['seller_email'] = $params['seller_email']; |
||
3689 | $sqlParams['next_number_invoice'] = $params['next_number_invoice']; |
||
3690 | $sqlParams['invoice_series'] = $params['invoice_series']; |
||
3691 | } |
||
3692 | |||
3693 | return Database::update( |
||
3694 | Database::get_main_table(self::TABLE_GLOBAL_CONFIG), |
||
3695 | $sqlParams, |
||
3696 | ['id = ?' => 1] |
||
3697 | ); |
||
3698 | } |
||
3699 | |||
3700 | /** |
||
3701 | * get Global Parameters. |
||
3702 | * |
||
3703 | * @return array |
||
3704 | */ |
||
3705 | public function getGlobalParameters() |
||
3706 | { |
||
3707 | return Database::select( |
||
3708 | '*', |
||
3709 | Database::get_main_table(self::TABLE_GLOBAL_CONFIG), |
||
3710 | ['id = ?' => 1], |
||
3711 | 'first' |
||
3712 | ); |
||
3713 | } |
||
3714 | |||
3715 | /** |
||
3716 | * @return bool |
||
3717 | */ |
||
3718 | public function checkTaxEnabledInProduct(int $productType) |
||
3719 | { |
||
3720 | if (empty($this->get('tax_enable') === 'true')) { |
||
3721 | return false; |
||
3722 | } |
||
3723 | |||
3724 | $globalParameters = $this->getGlobalParameters(); |
||
3725 | $taxAppliesTo = $globalParameters['tax_applies_to']; |
||
3726 | if ($taxAppliesTo == self::TAX_APPLIES_TO_ALL) { |
||
3727 | return true; |
||
3728 | } |
||
3729 | |||
3730 | if ($taxAppliesTo == $productType) { |
||
3731 | return true; |
||
3732 | } |
||
3733 | |||
3734 | return false; |
||
3735 | } |
||
3736 | |||
3737 | /** |
||
3738 | * Get the path. |
||
3739 | * |
||
3740 | * @param string $var path variable |
||
3741 | * |
||
3742 | * @return string path |
||
3743 | */ |
||
3744 | public function getPath($var) |
||
3745 | { |
||
3746 | $pluginPath = api_get_path(WEB_PLUGIN_PATH).'buycourses/'; |
||
3747 | $paths = [ |
||
3748 | 'SERVICE_IMAGES' => $pluginPath.'uploads/services/images/', |
||
3749 | 'SRC' => $pluginPath.'src/', |
||
3750 | 'VIEW' => $pluginPath.'view/', |
||
3751 | 'UPLOADS' => $pluginPath.'uploads/', |
||
3752 | 'LANGUAGES' => $pluginPath.'lang/', |
||
3753 | 'RESOURCES' => $pluginPath.'resources/', |
||
3754 | 'RESOURCES_IMG' => $pluginPath.'resources/img/', |
||
3755 | 'RESOURCES_CSS' => $pluginPath.'resources/css/', |
||
3756 | 'RESOURCES_JS' => $pluginPath.'resources/js/', |
||
3757 | ]; |
||
3758 | |||
3759 | return $paths[$var]; |
||
3760 | } |
||
3761 | |||
3762 | /** |
||
3763 | * @return array |
||
3764 | */ |
||
3765 | public function getBuyCoursePluginPrice(Session $session) |
||
3766 | { |
||
3767 | // start buycourse validation |
||
3768 | // display the course price and buy button if the buycourses plugin is enabled and this course is configured |
||
3769 | $isThisCourseInSale = $this->buyCoursesForGridCatalogValidator($session->getId(), self::PRODUCT_TYPE_SESSION); |
||
3770 | $return = []; |
||
3771 | |||
3772 | if ($isThisCourseInSale) { |
||
3773 | // set the Price label |
||
3774 | $return['html'] = $isThisCourseInSale['html']; |
||
3775 | // set the Buy button instead register. |
||
3776 | if ($isThisCourseInSale['verificator']) { |
||
3777 | $return['buy_button'] = $this->returnBuyCourseButton($session->getId(), self::PRODUCT_TYPE_SESSION); |
||
3778 | } |
||
3779 | } |
||
3780 | // end buycourse validation |
||
3781 | return $return; |
||
3782 | } |
||
3783 | |||
3784 | /** |
||
3785 | * Register a coupon sale. |
||
3786 | * |
||
3787 | * @param int $saleId The sale ID |
||
3788 | * @param int $couponId The coupon ID |
||
3789 | * |
||
3790 | * @return int |
||
3791 | */ |
||
3792 | public function registerCouponSale(int $saleId, int $couponId) |
||
3793 | { |
||
3794 | $sale = $this->getSale($saleId); |
||
3795 | |||
3796 | if (empty($sale)) { |
||
3797 | return false; |
||
3798 | } |
||
3799 | |||
3800 | $values = [ |
||
3801 | 'coupon_id' => $couponId, |
||
3802 | 'sale_id' => $saleId, |
||
3803 | ]; |
||
3804 | |||
3805 | return Database::insert(self::TABLE_COUPON_SALE, $values); |
||
3806 | } |
||
3807 | |||
3808 | /** |
||
3809 | * Register a coupon service sale. |
||
3810 | * |
||
3811 | * @param int $saleId The sale ID |
||
3812 | * @param int $couponId The coupon ID |
||
3813 | * |
||
3814 | * @return int |
||
3815 | */ |
||
3816 | public function registerCouponServiceSale(int $saleId, int $couponId) |
||
3817 | { |
||
3818 | $sale = $this->getSale($saleId); |
||
3819 | |||
3820 | if (empty($sale)) { |
||
3821 | return false; |
||
3822 | } |
||
3823 | |||
3824 | $values = [ |
||
3825 | 'coupon_id' => $couponId, |
||
3826 | 'service_sale_id' => $saleId, |
||
3827 | ]; |
||
3828 | |||
3829 | return Database::insert(self::TABLE_COUPON_SERVICE_SALE, $values); |
||
3830 | } |
||
3831 | |||
3832 | /** |
||
3833 | * Register a coupon sale. |
||
3834 | * |
||
3835 | * @param int $saleId The sale ID |
||
3836 | * @param int $couponId The coupon ID |
||
3837 | * |
||
3838 | * @return int |
||
3839 | */ |
||
3840 | public function registerCouponSubscriptionSale(int $saleId, int $couponId) |
||
3841 | { |
||
3842 | $sale = $this->getSubscriptionSale($saleId); |
||
3843 | |||
3844 | if (empty($sale)) { |
||
3845 | return false; |
||
3846 | } |
||
3847 | |||
3848 | $values = [ |
||
3849 | 'coupon_id' => (int) $couponId, |
||
3850 | 'sale_id' => (int) $saleId, |
||
3851 | ]; |
||
3852 | |||
3853 | return Database::insert(self::TABLE_COUPON_SUBSCRIPTION_SALE, $values); |
||
3854 | } |
||
3855 | |||
3856 | /** |
||
3857 | * Add a new coupon. |
||
3858 | */ |
||
3859 | public function addNewCoupon(array $coupon): bool |
||
3860 | { |
||
3861 | $couponId = $this->registerCoupon($coupon); |
||
3862 | if ($couponId) { |
||
3863 | if (isset($coupon['courses'])) { |
||
3864 | foreach ($coupon['courses'] as $course) { |
||
3865 | $this->registerCouponItem($couponId, self::PRODUCT_TYPE_COURSE, $course); |
||
3866 | } |
||
3867 | } |
||
3868 | |||
3869 | if (isset($coupon['sessions'])) { |
||
3870 | foreach ($coupon['sessions'] as $session) { |
||
3871 | $this->registerCouponItem($couponId, self::PRODUCT_TYPE_SESSION, $session); |
||
3872 | } |
||
3873 | } |
||
3874 | |||
3875 | if (isset($coupon['services'])) { |
||
3876 | foreach ($coupon['services'] as $service) { |
||
3877 | $this->registerCouponService($couponId, $service); |
||
3878 | } |
||
3879 | } |
||
3880 | |||
3881 | return true; |
||
3882 | } else { |
||
3883 | Display::addFlash( |
||
3884 | Display::return_message( |
||
3885 | $this->get_lang('CouponErrorInsert'), |
||
3886 | 'error', |
||
3887 | false |
||
3888 | ) |
||
3889 | ); |
||
3890 | |||
3891 | return false; |
||
3892 | } |
||
3893 | } |
||
3894 | |||
3895 | /** |
||
3896 | * Add a new coupon. |
||
3897 | * |
||
3898 | * @return bool |
||
3899 | */ |
||
3900 | public function updateCouponData(array $coupon) |
||
3901 | { |
||
3902 | $this->updateCoupon($coupon); |
||
3903 | $this->deleteCouponItemsByCoupon(self::PRODUCT_TYPE_COURSE, $coupon['id']); |
||
3904 | $this->deleteCouponItemsByCoupon(self::PRODUCT_TYPE_SESSION, $coupon['id']); |
||
3905 | $this->deleteCouponServicesByCoupon($coupon['id']); |
||
3906 | |||
3907 | if (isset($coupon['courses'])) { |
||
3908 | foreach ($coupon['courses'] as $course) { |
||
3909 | $this->registerCouponItem($coupon['id'], self::PRODUCT_TYPE_COURSE, $course); |
||
3910 | } |
||
3911 | } |
||
3912 | |||
3913 | if (isset($coupon['sessions'])) { |
||
3914 | foreach ($coupon['sessions'] as $session) { |
||
3915 | $this->registerCouponItem($coupon['id'], self::PRODUCT_TYPE_SESSION, $session); |
||
3916 | } |
||
3917 | } |
||
3918 | |||
3919 | if (isset($coupon['services'])) { |
||
3920 | foreach ($coupon['services'] as $service) { |
||
3921 | $this->registerCouponService($coupon['id'], $service); |
||
3922 | } |
||
3923 | } |
||
3924 | |||
3925 | return true; |
||
3926 | } |
||
3927 | |||
3928 | /** |
||
3929 | * Update coupons delivered. |
||
3930 | * |
||
3931 | * @param int $couponId The coupon ID |
||
3932 | * |
||
3933 | * @return bool |
||
3934 | */ |
||
3935 | public function updateCouponDelivered(int $couponId) |
||
3936 | { |
||
3937 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
3938 | |||
3939 | $sql = "UPDATE $couponTable |
||
3940 | SET delivered = delivered+1 |
||
3941 | WHERE id = $couponId"; |
||
3942 | |||
3943 | Database::query($sql); |
||
3944 | } |
||
3945 | |||
3946 | /** |
||
3947 | * Get coupon info. |
||
3948 | * |
||
3949 | * @param int $couponId The coupon ID |
||
3950 | * |
||
3951 | * @return array The coupon data |
||
3952 | */ |
||
3953 | public function getCouponInfo(int $couponId) |
||
3954 | { |
||
3955 | $coupon = $this->getDataCoupon($couponId); |
||
3956 | |||
3957 | $couponRelCourses = $this->getItemsCoupons($couponId, self::PRODUCT_TYPE_COURSE); |
||
3958 | $couponRelSessions = $this->getItemsCoupons($couponId, self::PRODUCT_TYPE_SESSION); |
||
3959 | $couponRelServices = $this->getServicesCoupons($couponId); |
||
3960 | |||
3961 | $coupon['courses'] = $couponRelCourses; |
||
3962 | $coupon['sessions'] = $couponRelSessions; |
||
3963 | $coupon['services'] = $couponRelServices; |
||
3964 | |||
3965 | return $coupon; |
||
3966 | } |
||
3967 | |||
3968 | /** |
||
3969 | * Get a list of coupons. |
||
3970 | * |
||
3971 | * @param int $status The coupons activation status |
||
3972 | * |
||
3973 | * @return array Coupons data |
||
3974 | */ |
||
3975 | public function getCouponsListByStatus(int $status) |
||
3976 | { |
||
3977 | $coupons = $this->getDataCoupons($status); |
||
3978 | |||
3979 | return $coupons; |
||
3980 | } |
||
3981 | |||
3982 | /** |
||
3983 | * Get the coupon data. |
||
3984 | * |
||
3985 | * @return array The coupon data |
||
3986 | */ |
||
3987 | public function getCoupon(int $couponId, int $productType, int $productId) |
||
3988 | { |
||
3989 | $coupon = $this->getDataCoupon($couponId, $productType, $productId); |
||
3990 | |||
3991 | return $coupon; |
||
3992 | } |
||
3993 | |||
3994 | /** |
||
3995 | * Get data of the coupon code. |
||
3996 | * |
||
3997 | * @param string $couponCode The coupon code |
||
3998 | * @param int $productId The product ID |
||
3999 | * @param int $productType The product type |
||
4000 | * |
||
4001 | * @return array The coupon data |
||
4002 | */ |
||
4003 | public function getCouponByCode(string $couponCode, int $productType = null, int $productId = null) |
||
4004 | { |
||
4005 | $coupon = $this->getDataCouponByCode($couponCode, $productType, $productId); |
||
4006 | |||
4007 | return $coupon; |
||
4008 | } |
||
4009 | |||
4010 | /** |
||
4011 | * Get data of the coupon code for a service. |
||
4012 | * |
||
4013 | * @param int $couponId The coupon ID |
||
4014 | * @param int $serviceId The product ID |
||
4015 | * |
||
4016 | * @return array The coupon data |
||
4017 | */ |
||
4018 | public function getCouponService(int $couponId, int $serviceId) |
||
4019 | { |
||
4020 | $coupon = $this->getDataCouponService($couponId, $serviceId); |
||
4021 | |||
4022 | return $coupon; |
||
4023 | } |
||
4024 | |||
4025 | /** |
||
4026 | * Get data of the coupon code for a service. |
||
4027 | * |
||
4028 | * @param string $couponCode The coupon code code |
||
4029 | * @param int $serviceId The product id |
||
4030 | * |
||
4031 | * @return array The coupon data |
||
4032 | */ |
||
4033 | public function getCouponServiceByCode(string $couponCode, int $serviceId) |
||
4034 | { |
||
4035 | $coupon = $this->getDataCouponServiceByCode($couponCode, $serviceId); |
||
4036 | |||
4037 | return $coupon; |
||
4038 | } |
||
4039 | |||
4040 | /** |
||
4041 | * Get the coupon code of a item sale. |
||
4042 | * |
||
4043 | * @param int $saleId The sale ID |
||
4044 | * |
||
4045 | * @return string The coupon code |
||
4046 | */ |
||
4047 | public function getSaleCouponCode(int $saleId) |
||
4048 | { |
||
4049 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
4050 | $couponSaleTable = Database::get_main_table(self::TABLE_COUPON_SALE); |
||
4051 | |||
4052 | $couponFrom = " |
||
4053 | $couponTable c |
||
4054 | INNER JOIN $couponSaleTable s |
||
4055 | on c.id = s.coupon_id |
||
4056 | "; |
||
4057 | |||
4058 | $couponCode = Database::select( |
||
4059 | ['c.code'], |
||
4060 | $couponFrom, |
||
4061 | [ |
||
4062 | 'where' => [ |
||
4063 | 's.sale_id = ? ' => $saleId, |
||
4064 | ], |
||
4065 | ], |
||
4066 | 'first' |
||
4067 | ); |
||
4068 | |||
4069 | return $couponCode['code']; |
||
4070 | } |
||
4071 | |||
4072 | /** |
||
4073 | * Get the coupon code of a service sale. |
||
4074 | * |
||
4075 | * @param int $serviceSaleId The service sale ID |
||
4076 | * |
||
4077 | * @return string The coupon code |
||
4078 | */ |
||
4079 | public function getServiceSaleCouponCode(int $serviceSaleId) |
||
4080 | { |
||
4081 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
4082 | $couponServiceSaleTable = Database::get_main_table(self::TABLE_COUPON_SERVICE_SALE); |
||
4083 | |||
4084 | $couponFrom = " |
||
4085 | $couponTable c |
||
4086 | INNER JOIN $couponServiceSaleTable s |
||
4087 | on c.id = s.coupon_id |
||
4088 | "; |
||
4089 | |||
4090 | $couponCode = Database::select( |
||
4091 | ['c.code'], |
||
4092 | $couponFrom, |
||
4093 | [ |
||
4094 | 'where' => [ |
||
4095 | 's.service_sale_id = ? ' => $serviceSaleId, |
||
4096 | ], |
||
4097 | ], |
||
4098 | 'first' |
||
4099 | ); |
||
4100 | |||
4101 | return $couponCode['code']; |
||
4102 | } |
||
4103 | |||
4104 | /** |
||
4105 | * @return array |
||
4106 | */ |
||
4107 | public function getCecabankSignature(string $saleReference, float $price) |
||
4108 | { |
||
4109 | $urlOk = api_get_path(WEB_PLUGIN_PATH).'buycourses/src/cecabank_success.php'; |
||
4110 | $urlKo = api_get_path(WEB_PLUGIN_PATH).'buycourses/src/cecabank_cancel.php'; |
||
4111 | |||
4112 | $cecabankParams = $this->getCecabankParams(); |
||
4113 | $signature = $cecabankParams['crypto_key'] |
||
4114 | .$cecabankParams['merchant_id'] |
||
4115 | .$cecabankParams['acquirer_bin'] |
||
4116 | .$cecabankParams['terminal_id'] |
||
4117 | .$saleReference |
||
4118 | .$price * 100 |
||
4119 | .'978' |
||
4120 | .$cecabankParams['exponent'] |
||
4121 | .$cecabankParams['cypher'] |
||
4122 | .$urlOk |
||
4123 | .$urlKo; |
||
4124 | |||
4125 | $sha256 = hash('sha256', $signature); |
||
4126 | $signature = strtolower($sha256); |
||
4127 | |||
4128 | return $signature; |
||
4129 | } |
||
4130 | |||
4131 | /** |
||
4132 | * Register a subscription sale. |
||
4133 | * |
||
4134 | * @param int $productId The product ID |
||
4135 | * @param int $productType The product type |
||
4136 | * @param int $paymentType The payment type |
||
4137 | * @param int $duration The subscription duration |
||
4138 | * @param int $couponId The coupon ID |
||
4139 | * |
||
4140 | * @return int |
||
4141 | */ |
||
4142 | public function registerSubscriptionSale( |
||
4143 | int $productId, |
||
4144 | int $productType, |
||
4145 | int $paymentType, |
||
4146 | int $duration, |
||
4147 | int $couponId = null |
||
4148 | ) { |
||
4149 | if (!in_array( |
||
4150 | $paymentType, |
||
4151 | [ |
||
4152 | self::PAYMENT_TYPE_PAYPAL, |
||
4153 | self::PAYMENT_TYPE_TRANSFER, |
||
4154 | self::PAYMENT_TYPE_CULQI, |
||
4155 | self::PAYMENT_TYPE_TPV_REDSYS, |
||
4156 | self::PAYMENT_TYPE_STRIPE, |
||
4157 | self::PAYMENT_TYPE_TPV_CECABANK, |
||
4158 | ] |
||
4159 | ) |
||
4160 | ) { |
||
4161 | return false; |
||
4162 | } |
||
4163 | |||
4164 | $entityManager = Database::getManager(); |
||
4165 | $item = $this->getSubscriptionItem($productId, $productType); |
||
4166 | |||
4167 | if (empty($item)) { |
||
4168 | return false; |
||
4169 | } |
||
4170 | |||
4171 | $productName = ''; |
||
4172 | if ($item['product_type'] == self::PRODUCT_TYPE_COURSE) { |
||
4173 | $course = $entityManager->find('ChamiloCoreBundle:Course', $item['product_id']); |
||
4174 | |||
4175 | if (empty($course)) { |
||
4176 | return false; |
||
4177 | } |
||
4178 | |||
4179 | $productName = $course->getTitle(); |
||
4180 | } elseif ($item['product_type'] == self::PRODUCT_TYPE_SESSION) { |
||
4181 | $session = $entityManager->find('ChamiloCoreBundle:Session', $item['product_id']); |
||
4182 | |||
4183 | if (empty($session)) { |
||
4184 | return false; |
||
4185 | } |
||
4186 | |||
4187 | $productName = $session->getName(); |
||
4188 | } |
||
4189 | |||
4190 | if ($couponId != null) { |
||
4191 | $coupon = $this->getCoupon($couponId, $item['product_type'], $item['product_id']); |
||
4192 | } |
||
4193 | |||
4194 | $couponDiscount = 0; |
||
4195 | $priceWithoutDiscount = 0; |
||
4196 | if ($coupon != null) { |
||
4197 | if ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_AMOUNT) { |
||
4198 | $couponDiscount = $coupon['discount_amount']; |
||
4199 | } elseif ($coupon['discount_type'] == self::COUPON_DISCOUNT_TYPE_PERCENTAGE) { |
||
4200 | $couponDiscount = ($item['price'] * $coupon['discount_amount']) / 100; |
||
4201 | } |
||
4202 | $priceWithoutDiscount = $item['price']; |
||
4203 | } |
||
4204 | $item['price'] = $item['price'] - $couponDiscount; |
||
4205 | $price = $item['price']; |
||
4206 | $priceWithoutTax = null; |
||
4207 | $taxPerc = null; |
||
4208 | $taxAmount = 0; |
||
4209 | $taxEnable = $this->get('tax_enable') === 'true'; |
||
4210 | $globalParameters = $this->getGlobalParameters(); |
||
4211 | $taxAppliesTo = $globalParameters['tax_applies_to']; |
||
4212 | |||
4213 | if ($taxEnable && |
||
4214 | ( |
||
4215 | $taxAppliesTo == self::TAX_APPLIES_TO_ALL || |
||
4216 | ($taxAppliesTo == self::TAX_APPLIES_TO_ONLY_COURSE && $item['product_type'] == self::PRODUCT_TYPE_COURSE) || |
||
4217 | ($taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SESSION && $item['product_type'] == self::PRODUCT_TYPE_SESSION) |
||
4218 | ) |
||
4219 | ) { |
||
4220 | $priceWithoutTax = $item['price']; |
||
4221 | $globalTaxPerc = $globalParameters['global_tax_perc']; |
||
4222 | $precision = 2; |
||
4223 | $taxPerc = is_null($item['tax_perc']) ? $globalTaxPerc : $item['tax_perc']; |
||
4224 | $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); |
||
4225 | $price = $priceWithoutTax + $taxAmount; |
||
4226 | } |
||
4227 | |||
4228 | $subscriptionEnd = date('y:m:d', strtotime('+'.$duration.' days')); |
||
4229 | |||
4230 | $values = [ |
||
4231 | 'reference' => $this->generateReference( |
||
4232 | api_get_user_id(), |
||
4233 | $item['product_type'], |
||
4234 | $item['product_id'] |
||
4235 | ), |
||
4236 | 'currency_id' => $item['currency_id'], |
||
4237 | 'date' => api_get_utc_datetime(), |
||
4238 | 'user_id' => api_get_user_id(), |
||
4239 | 'product_type' => $item['product_type'], |
||
4240 | 'product_name' => $productName, |
||
4241 | 'product_id' => $item['product_id'], |
||
4242 | 'price' => $price, |
||
4243 | 'price_without_tax' => $priceWithoutTax, |
||
4244 | 'tax_perc' => $taxPerc, |
||
4245 | 'tax_amount' => $taxAmount, |
||
4246 | 'status' => self::SALE_STATUS_PENDING, |
||
4247 | 'payment_type' => $paymentType, |
||
4248 | 'price_without_discount' => $priceWithoutDiscount, |
||
4249 | 'discount_amount' => $couponDiscount, |
||
4250 | 'subscription_end' => $subscriptionEnd, |
||
4251 | ]; |
||
4252 | |||
4253 | return Database::insert(self::TABLE_SUBSCRIPTION_SALE, $values); |
||
4254 | } |
||
4255 | |||
4256 | /** |
||
4257 | * Add a new subscription. |
||
4258 | * |
||
4259 | * @return bool |
||
4260 | */ |
||
4261 | public function addNewSubscription(array $subscription) |
||
4262 | { |
||
4263 | $result = false; |
||
4264 | |||
4265 | if (isset($subscription['frequencies'])) { |
||
4266 | foreach ($subscription['frequencies'] as $frequency) { |
||
4267 | $subscriptionDb = $this->getSubscription($subscription['product_type'], $subscription['product_id'], $frequency['duration']); |
||
4268 | |||
4269 | if (!isset($subscriptionDb) || empty($subscription)) { |
||
4270 | Display::addFlash( |
||
4271 | Display::return_message( |
||
4272 | $this->get_lang('SubscriptionAlreadyExists').' ('.$frequency['duration'].')', |
||
4273 | 'error', |
||
4274 | false |
||
4275 | ) |
||
4276 | ); |
||
4277 | |||
4278 | return false; |
||
4279 | } else { |
||
4280 | $subscriptionId = $this->registerSubscription($subscription, $frequency); |
||
4281 | if ($subscriptionId) { |
||
4282 | $result = true; |
||
4283 | } else { |
||
4284 | Display::addFlash( |
||
4285 | Display::return_message( |
||
4286 | $this->get_lang('SubscriptionErrorInsert'), |
||
4287 | 'error', |
||
4288 | false |
||
4289 | ) |
||
4290 | ); |
||
4291 | |||
4292 | return false; |
||
4293 | } |
||
4294 | } |
||
4295 | } |
||
4296 | } else { |
||
4297 | Display::addFlash( |
||
4298 | Display::return_message( |
||
4299 | $this->get_lang('FrequenciesNotSetError'), |
||
4300 | 'error', |
||
4301 | false |
||
4302 | ) |
||
4303 | ); |
||
4304 | |||
4305 | return false; |
||
4306 | } |
||
4307 | |||
4308 | return $result; |
||
4309 | } |
||
4310 | |||
4311 | /** |
||
4312 | * Add a new subscription. |
||
4313 | * |
||
4314 | * @return bool |
||
4315 | */ |
||
4316 | public function updateSubscriptions(int $productType, int $productId, int $taxPerc) |
||
4317 | { |
||
4318 | $this->updateSubscription($productType, $productId, $taxPerc); |
||
4319 | } |
||
4320 | |||
4321 | /** |
||
4322 | * Delete a subscription. |
||
4323 | * |
||
4324 | * @return int |
||
4325 | */ |
||
4326 | public function deleteSubscription(int $productType, int $productId, int $duration) |
||
4327 | { |
||
4328 | return Database::delete( |
||
4329 | Database::get_main_table(self::TABLE_SUBSCRIPTION), |
||
4330 | [ |
||
4331 | 'product_type = ? AND ' => (int) $productType, |
||
4332 | 'product_id = ? AND ' => (int) $productId, |
||
4333 | 'duration = ? ' => (int) $duration, |
||
4334 | ] |
||
4335 | ); |
||
4336 | } |
||
4337 | |||
4338 | /** |
||
4339 | * Get a list of subscriptions by product ID and type. |
||
4340 | * |
||
4341 | * @param string $productId The product ID |
||
4342 | * @param int $productType The product type |
||
4343 | * |
||
4344 | * @return array Subscriptions data |
||
4345 | */ |
||
4346 | public function getSubscriptions($productType, $productId) |
||
4347 | { |
||
4348 | $subscriptions = $this->getDataSubscriptions($productType, $productId); |
||
4349 | |||
4350 | return $subscriptions; |
||
4351 | } |
||
4352 | |||
4353 | /** |
||
4354 | * Get data of the subscription. |
||
4355 | * |
||
4356 | * @return array The subscription data |
||
4357 | */ |
||
4358 | public function getSubscription(int $productType, int $productId, int $duration, array $coupon = null) |
||
4359 | { |
||
4360 | $subscription = $this->getDataSubscription($productType, $productId, $duration); |
||
4361 | |||
4362 | $currency = $this->getSelectedCurrency(); |
||
4363 | $isoCode = $currency['iso_code']; |
||
4364 | |||
4365 | $subscription['iso_code'] = $isoCode; |
||
4366 | |||
4367 | $this->setPriceSettings($subscription, self::TAX_APPLIES_TO_ONLY_COURSE, $coupon); |
||
4368 | |||
4369 | return $subscription; |
||
4370 | } |
||
4371 | |||
4372 | /** |
||
4373 | * Get subscription sale data by ID. |
||
4374 | * |
||
4375 | * @param int $saleId The sale ID |
||
4376 | * |
||
4377 | * @return array |
||
4378 | */ |
||
4379 | public function getSubscriptionSale(int $saleId) |
||
4380 | { |
||
4381 | return Database::select( |
||
4382 | '*', |
||
4383 | Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE), |
||
4384 | [ |
||
4385 | 'where' => ['id = ?' => $saleId], |
||
4386 | ], |
||
4387 | 'first' |
||
4388 | ); |
||
4389 | } |
||
4390 | |||
4391 | /** |
||
4392 | * Complete subscription sale process. Update sale status to completed. |
||
4393 | * |
||
4394 | * @param int $saleId The subscription sale ID |
||
4395 | * |
||
4396 | * @return bool |
||
4397 | */ |
||
4398 | public function completeSubscriptionSale(int $saleId) |
||
4399 | { |
||
4400 | $sale = $this->getSubscriptionSale($saleId); |
||
4401 | |||
4402 | if ($sale['status'] == self::SALE_STATUS_COMPLETED) { |
||
4403 | return true; |
||
4404 | } |
||
4405 | |||
4406 | $saleIsCompleted = false; |
||
4407 | switch ($sale['product_type']) { |
||
4408 | case self::PRODUCT_TYPE_COURSE: |
||
4409 | $course = api_get_course_info_by_id($sale['product_id']); |
||
4410 | $saleIsCompleted = CourseManager::subscribeUser($sale['user_id'], $course['code']); |
||
4411 | break; |
||
4412 | case self::PRODUCT_TYPE_SESSION: |
||
4413 | SessionManager::subscribeUsersToSession( |
||
4414 | $sale['product_id'], |
||
4415 | [$sale['user_id']], |
||
4416 | api_get_session_visibility($sale['product_id']), |
||
4417 | false |
||
4418 | ); |
||
4419 | |||
4420 | $saleIsCompleted = true; |
||
4421 | break; |
||
4422 | } |
||
4423 | |||
4424 | if ($saleIsCompleted) { |
||
4425 | $this->updateSubscriptionSaleStatus($sale['id'], self::SALE_STATUS_COMPLETED); |
||
4426 | if ($this->get('invoicing_enable') === 'true') { |
||
4427 | $this->setInvoice($sale['id']); |
||
4428 | } |
||
4429 | } |
||
4430 | |||
4431 | return $saleIsCompleted; |
||
4432 | } |
||
4433 | |||
4434 | /** |
||
4435 | * Update subscription sale status to canceled. |
||
4436 | * |
||
4437 | * @param int $saleId The subscription sale ID |
||
4438 | */ |
||
4439 | public function cancelSubscriptionSale(int $saleId) |
||
4440 | { |
||
4441 | $this->updateSubscriptionSaleStatus($saleId, self::SALE_STATUS_CANCELED); |
||
4442 | } |
||
4443 | |||
4444 | /** |
||
4445 | * Get a list of subscription sales by the status. |
||
4446 | * |
||
4447 | * @param int $status The status to filter |
||
4448 | * |
||
4449 | * @return array The sale list. Otherwise return false |
||
4450 | */ |
||
4451 | public function getSubscriptionSaleListByStatus(int $status = self::SALE_STATUS_PENDING) |
||
4452 | { |
||
4453 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
4454 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
4455 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
4456 | |||
4457 | $innerJoins = " |
||
4458 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
4459 | INNER JOIN $userTable u ON s.user_id = u.id |
||
4460 | "; |
||
4461 | |||
4462 | return Database::select( |
||
4463 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
4464 | "$saleTable s $innerJoins", |
||
4465 | [ |
||
4466 | 'where' => ['s.status = ?' => $status], |
||
4467 | 'order' => 'id DESC', |
||
4468 | ] |
||
4469 | ); |
||
4470 | } |
||
4471 | |||
4472 | /** |
||
4473 | * Get the list statuses for subscriptions sales. |
||
4474 | * |
||
4475 | * @param string $dateStart |
||
4476 | * @param string $dateEnd |
||
4477 | * |
||
4478 | * @throws Exception |
||
4479 | * |
||
4480 | * @return array |
||
4481 | */ |
||
4482 | public function getSubscriptionSaleListReport(string $dateStart = null, string $dateEnd = null) |
||
4483 | { |
||
4484 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
4485 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
4486 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
4487 | $innerJoins = " |
||
4488 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
4489 | INNER JOIN $userTable u ON s.user_id = u.id |
||
4490 | "; |
||
4491 | $list = Database::select( |
||
4492 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
4493 | "$saleTable s $innerJoins", |
||
4494 | [ |
||
4495 | 'order' => 'id DESC', |
||
4496 | ] |
||
4497 | ); |
||
4498 | $listExportTemp = []; |
||
4499 | $listExport = []; |
||
4500 | $textStatus = null; |
||
4501 | $paymentTypes = $this->getPaymentTypes(); |
||
4502 | $productTypes = $this->getProductTypes(); |
||
4503 | foreach ($list as $item) { |
||
4504 | $statusSaleOrder = $item['status']; |
||
4505 | switch ($statusSaleOrder) { |
||
4506 | case 0: |
||
4507 | $textStatus = $this->get_lang('SaleStatusPending'); |
||
4508 | break; |
||
4509 | case 1: |
||
4510 | $textStatus = $this->get_lang('SaleStatusCompleted'); |
||
4511 | break; |
||
4512 | case -1: |
||
4513 | $textStatus = $this->get_lang('SaleStatusCanceled'); |
||
4514 | break; |
||
4515 | } |
||
4516 | $dateFilter = new DateTime($item['date']); |
||
4517 | $listExportTemp[] = [ |
||
4518 | 'id' => $item['id'], |
||
4519 | 'reference' => $item['reference'], |
||
4520 | 'status' => $textStatus, |
||
4521 | 'status_filter' => $item['status'], |
||
4522 | 'date' => $dateFilter->format('Y-m-d'), |
||
4523 | 'order_time' => $dateFilter->format('H:i:s'), |
||
4524 | 'price' => $item['iso_code'].' '.$item['price'], |
||
4525 | 'product_type' => $productTypes[$item['product_type']], |
||
4526 | 'product_name' => $item['product_name'], |
||
4527 | 'payment_type' => $paymentTypes[$item['payment_type']], |
||
4528 | 'complete_user_name' => api_get_person_name($item['firstname'], $item['lastname']), |
||
4529 | 'email' => $item['email'], |
||
4530 | ]; |
||
4531 | } |
||
4532 | $listExport[] = [ |
||
4533 | get_lang('Number'), |
||
4534 | $this->get_lang('OrderStatus'), |
||
4535 | $this->get_lang('OrderDate'), |
||
4536 | $this->get_lang('OrderTime'), |
||
4537 | $this->get_lang('PaymentMethod'), |
||
4538 | $this->get_lang('SalePrice'), |
||
4539 | $this->get_lang('ProductType'), |
||
4540 | $this->get_lang('ProductName'), |
||
4541 | $this->get_lang('UserName'), |
||
4542 | get_lang('Email'), |
||
4543 | ]; |
||
4544 | //Validation Export |
||
4545 | $dateStart = strtotime($dateStart); |
||
4546 | $dateEnd = strtotime($dateEnd); |
||
4547 | foreach ($listExportTemp as $item) { |
||
4548 | $dateFilter = strtotime($item['date']); |
||
4549 | if (($dateFilter >= $dateStart) && ($dateFilter <= $dateEnd)) { |
||
4550 | $listExport[] = [ |
||
4551 | 'id' => $item['id'], |
||
4552 | 'status' => $item['status'], |
||
4553 | 'date' => $item['date'], |
||
4554 | 'order_time' => $item['order_time'], |
||
4555 | 'payment_type' => $item['payment_type'], |
||
4556 | 'price' => $item['price'], |
||
4557 | 'product_type' => $item['product_type'], |
||
4558 | 'product_name' => $item['product_name'], |
||
4559 | 'complete_user_name' => $item['complete_user_name'], |
||
4560 | 'email' => $item['email'], |
||
4561 | ]; |
||
4562 | } |
||
4563 | } |
||
4564 | |||
4565 | return $listExport; |
||
4566 | } |
||
4567 | |||
4568 | /** |
||
4569 | * Get a list of subscription sales by the user. |
||
4570 | * |
||
4571 | * @param string $term The search term |
||
4572 | * |
||
4573 | * @return array The sale list. Otherwise return false |
||
4574 | */ |
||
4575 | public function getSubscriptionSaleListByUser(string $term) |
||
4576 | { |
||
4577 | $term = trim($term); |
||
4578 | |||
4579 | if (empty($term)) { |
||
4580 | return []; |
||
4581 | } |
||
4582 | |||
4583 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
4584 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
4585 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
4586 | $innerJoins = " |
||
4587 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
4588 | INNER JOIN $userTable u ON s.user_id = u.id |
||
4589 | "; |
||
4590 | |||
4591 | return Database::select( |
||
4592 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
4593 | "$saleTable s $innerJoins", |
||
4594 | [ |
||
4595 | 'where' => [ |
||
4596 | 'u.username LIKE %?% OR ' => $term, |
||
4597 | 'u.lastname LIKE %?% OR ' => $term, |
||
4598 | 'u.firstname LIKE %?%' => $term, |
||
4599 | ], |
||
4600 | 'order' => 'id DESC', |
||
4601 | ] |
||
4602 | ); |
||
4603 | } |
||
4604 | |||
4605 | /** |
||
4606 | * Get a list of subscription sales by the user id. |
||
4607 | * |
||
4608 | * @param int $id The user id |
||
4609 | * |
||
4610 | * @return array The sale list. Otherwise return false |
||
4611 | */ |
||
4612 | public function getSubscriptionSaleListByUserId(int $id) |
||
4613 | { |
||
4614 | if (empty($id)) { |
||
4615 | return []; |
||
4616 | } |
||
4617 | |||
4618 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
4619 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
4620 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
4621 | |||
4622 | $innerJoins = " |
||
4623 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
4624 | INNER JOIN $userTable u ON s.user_id = u.id |
||
4625 | "; |
||
4626 | |||
4627 | return Database::select( |
||
4628 | ['c.iso_code', 'u.firstname', 'u.lastname', 's.*'], |
||
4629 | "$saleTable s $innerJoins", |
||
4630 | [ |
||
4631 | 'where' => [ |
||
4632 | 'u.id = ? AND s.status = ?' => [$id, self::SALE_STATUS_COMPLETED], |
||
4633 | ], |
||
4634 | 'order' => 'id DESC', |
||
4635 | ] |
||
4636 | ); |
||
4637 | } |
||
4638 | |||
4639 | /** |
||
4640 | * Get a list of subscription sales by date range. |
||
4641 | * |
||
4642 | * @return array The sale list. Otherwise return false |
||
4643 | */ |
||
4644 | public function getSubscriptionSaleListByDate(string $dateStart, string $dateEnd) |
||
4645 | { |
||
4646 | $dateStart = trim($dateStart); |
||
4647 | $dateEnd = trim($dateEnd); |
||
4648 | if (empty($dateStart)) { |
||
4649 | return []; |
||
4650 | } |
||
4651 | if (empty($dateEnd)) { |
||
4652 | return []; |
||
4653 | } |
||
4654 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
4655 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
4656 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
4657 | $innerJoins = " |
||
4658 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
4659 | INNER JOIN $userTable u ON s.user_id = u.id |
||
4660 | "; |
||
4661 | |||
4662 | return Database::select( |
||
4663 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
4664 | "$saleTable s $innerJoins", |
||
4665 | [ |
||
4666 | 'where' => [ |
||
4667 | 's.date BETWEEN ? AND ' => $dateStart, |
||
4668 | ' ? ' => $dateEnd, |
||
4669 | ], |
||
4670 | 'order' => 'id DESC', |
||
4671 | ] |
||
4672 | ); |
||
4673 | } |
||
4674 | |||
4675 | /** |
||
4676 | * Get a list of subscription sales by the user Email. |
||
4677 | * |
||
4678 | * @param string $term The search term |
||
4679 | * |
||
4680 | * @return array The sale list. Otherwise return false |
||
4681 | */ |
||
4682 | public function getSubscriptionSaleListByEmail(string $term) |
||
4683 | { |
||
4684 | $term = trim($term); |
||
4685 | if (empty($term)) { |
||
4686 | return []; |
||
4687 | } |
||
4688 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
4689 | $currencyTable = Database::get_main_table(self::TABLE_CURRENCY); |
||
4690 | $userTable = Database::get_main_table(TABLE_MAIN_USER); |
||
4691 | $innerJoins = " |
||
4692 | INNER JOIN $currencyTable c ON s.currency_id = c.id |
||
4693 | INNER JOIN $userTable u ON s.user_id = u.id |
||
4694 | "; |
||
4695 | |||
4696 | return Database::select( |
||
4697 | ['c.iso_code', 'u.firstname', 'u.lastname', 'u.email', 's.*'], |
||
4698 | "$saleTable s $innerJoins", |
||
4699 | [ |
||
4700 | 'where' => [ |
||
4701 | 'u.email LIKE %?% ' => $term, |
||
4702 | ], |
||
4703 | 'order' => 'id DESC', |
||
4704 | ] |
||
4705 | ); |
||
4706 | } |
||
4707 | |||
4708 | /** |
||
4709 | * Get subscription sale data by ID. |
||
4710 | * |
||
4711 | * @param string $date The date |
||
4712 | * |
||
4713 | * @return array |
||
4714 | */ |
||
4715 | public function getSubscriptionsDue(string $date) |
||
4716 | { |
||
4717 | return Database::select( |
||
4718 | 'id, user_id, product_id, product_type', |
||
4719 | Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE), |
||
4720 | [ |
||
4721 | 'where' => ['subscription_end < ? AND status <> ? AND (expired is NULL OR expired <> ?)' => [ |
||
4722 | $date, |
||
4723 | self::SALE_STATUS_COMPLETED, |
||
4724 | 1, |
||
4725 | ], |
||
4726 | ], |
||
4727 | ], |
||
4728 | 'first' |
||
4729 | ); |
||
4730 | } |
||
4731 | |||
4732 | /** |
||
4733 | * Get subscription sale data by ID. |
||
4734 | * |
||
4735 | * @param int $userId The user ID |
||
4736 | * @param int $productId The product ID |
||
4737 | * @param int $productType The product type |
||
4738 | * |
||
4739 | * @return array |
||
4740 | */ |
||
4741 | public function checkItemSubscriptionActive(int $userId, int $productId, int $productType) |
||
4742 | { |
||
4743 | return Database::select( |
||
4744 | '*', |
||
4745 | Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE), |
||
4746 | [ |
||
4747 | 'where' => ['subscription_end >= ? AND userId = ? AND productId = ? AND productType = ? AND status <> ?' => [ |
||
4748 | api_get_utc_datetime(), |
||
4749 | $userId, |
||
4750 | $productId, |
||
4751 | $productType, |
||
4752 | self::SALE_STATUS_COMPLETED, |
||
4753 | ], |
||
4754 | ], |
||
4755 | ], |
||
4756 | 'first' |
||
4757 | ); |
||
4758 | } |
||
4759 | |||
4760 | /** |
||
4761 | * Get subscription sale data by ID. |
||
4762 | * |
||
4763 | * @return array |
||
4764 | */ |
||
4765 | public function updateSubscriptionSaleExpirationStatus(int $id) |
||
4766 | { |
||
4767 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
4768 | |||
4769 | return Database::update( |
||
4770 | $saleTable, |
||
4771 | ['expired' => 1], |
||
4772 | ['id = ?' => $id] |
||
4773 | ); |
||
4774 | } |
||
4775 | |||
4776 | /** |
||
4777 | * Get the list of frequencies discount types. |
||
4778 | * |
||
4779 | * @return array |
||
4780 | */ |
||
4781 | public function getFrequencies() |
||
4782 | { |
||
4783 | $data = Database::select( |
||
4784 | '*', |
||
4785 | Database::get_main_table(self::TABLE_SUBSCRIPTION_PERIOD), |
||
4786 | [] |
||
4787 | ); |
||
4788 | |||
4789 | $frequenciesList = $this->getFrequenciesList(); |
||
4790 | $frequencies = []; |
||
4791 | |||
4792 | foreach ($data as $key => $items) { |
||
4793 | $frequencies[$items['duration']] = $items['name']; |
||
4794 | } |
||
4795 | |||
4796 | return $frequencies; |
||
4797 | } |
||
4798 | |||
4799 | /** |
||
4800 | * Get the list of frequencies discount types. |
||
4801 | * |
||
4802 | * @return array |
||
4803 | */ |
||
4804 | public function getFrequenciesList() |
||
4805 | { |
||
4806 | return Database::select( |
||
4807 | '*', |
||
4808 | Database::get_main_table(self::TABLE_SUBSCRIPTION_PERIOD), |
||
4809 | [] |
||
4810 | ); |
||
4811 | } |
||
4812 | |||
4813 | /** |
||
4814 | * Get the a frequency. |
||
4815 | * |
||
4816 | * @param int $duration The duration of the frequency value |
||
4817 | * |
||
4818 | * @return array |
||
4819 | */ |
||
4820 | public function selectFrequency(int $duration) |
||
4821 | { |
||
4822 | return Database::select( |
||
4823 | '*', |
||
4824 | Database::get_main_table(self::TABLE_SUBSCRIPTION_PERIOD), |
||
4825 | [ |
||
4826 | 'where' => [ |
||
4827 | 'duration = ?' => [ |
||
4828 | (int) $duration, |
||
4829 | ], |
||
4830 | ], |
||
4831 | ], |
||
4832 | 'first' |
||
4833 | ); |
||
4834 | } |
||
4835 | |||
4836 | /** |
||
4837 | * Add a new subscription frequency. |
||
4838 | * |
||
4839 | * @return array |
||
4840 | */ |
||
4841 | public function addFrequency(int $duration, string $name) |
||
4842 | { |
||
4843 | $values = [ |
||
4844 | 'duration' => $duration, |
||
4845 | 'name' => $name, |
||
4846 | ]; |
||
4847 | |||
4848 | return Database::insert(self::TABLE_SUBSCRIPTION_PERIOD, $values); |
||
4849 | } |
||
4850 | |||
4851 | /** |
||
4852 | * Update a subscription frequency. |
||
4853 | * |
||
4854 | * @return array |
||
4855 | */ |
||
4856 | public function updateFrequency(int $duration, string $name) |
||
4857 | { |
||
4858 | $periodTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_PERIOD); |
||
4859 | |||
4860 | return Database::update( |
||
4861 | $periodTable, |
||
4862 | ['name' => $name], |
||
4863 | ['duration = ?' => $duration] |
||
4864 | ); |
||
4865 | } |
||
4866 | |||
4867 | /** |
||
4868 | * Delete a subscription frequency. |
||
4869 | * |
||
4870 | * @return array |
||
4871 | */ |
||
4872 | public function deleteFrequency(int $duration) |
||
4873 | { |
||
4874 | return Database::delete( |
||
4875 | Database::get_main_table(self::TABLE_SUBSCRIPTION_PERIOD), |
||
4876 | [ |
||
4877 | 'duration = ?' => $duration, |
||
4878 | ] |
||
4879 | ); |
||
4880 | } |
||
4881 | |||
4882 | /** |
||
4883 | * @return string |
||
4884 | */ |
||
4885 | public function getSubscriptionSuccessMessage(array $saleInfo) |
||
4886 | { |
||
4887 | switch ($saleInfo['product_type']) { |
||
4888 | case self::PRODUCT_TYPE_COURSE: |
||
4889 | $courseInfo = api_get_course_info_by_id($saleInfo['product_id']); |
||
4890 | $url = api_get_course_url($courseInfo['code']); |
||
4891 | break; |
||
4892 | case self::PRODUCT_TYPE_SESSION: |
||
4893 | $sessionId = (int) $saleInfo['product_id']; |
||
4894 | $url = api_get_path(WEB_CODE_PATH).'session/index.php?session_id='.$sessionId; |
||
4895 | break; |
||
4896 | default: |
||
4897 | $url = '#'; |
||
4898 | } |
||
4899 | |||
4900 | return Display::return_message( |
||
4901 | sprintf( |
||
4902 | $this->get_lang('SubscriptionToCourseXSuccessful'), |
||
4903 | $url, |
||
4904 | $saleInfo['product_name'] |
||
4905 | ), |
||
4906 | 'success', |
||
4907 | false |
||
4908 | ); |
||
4909 | } |
||
4910 | |||
4911 | /** |
||
4912 | * @return string |
||
4913 | */ |
||
4914 | public static function returnPagination( |
||
4915 | string $baseUrl, |
||
4916 | string $currentPage, |
||
4917 | string $pagesCount, |
||
4918 | string $totalItems, |
||
4919 | array $extraQueryParams = [] |
||
4920 | ) { |
||
4921 | $queryParams = HttpRequest::createFromGlobals()->query->all(); |
||
4922 | |||
4923 | unset($queryParams['page']); |
||
4924 | |||
4925 | $url = $baseUrl.'?'.http_build_query( |
||
4926 | array_merge($queryParams, $extraQueryParams) |
||
4927 | ); |
||
4928 | |||
4929 | return Display::getPagination($url, $currentPage, $pagesCount, $totalItems); |
||
4930 | } |
||
4931 | |||
4932 | /** |
||
4933 | * Returns the javascript to set the sales report table for courses. |
||
4934 | */ |
||
4935 | public static function getSalesReportScript(array $sales = [], bool $invoicingEnable = false) |
||
4936 | { |
||
4937 | $cols = " |
||
4938 | '".preg_replace("/'/", "\\'", get_plugin_lang('OrderReference', 'BuyCoursesPlugin'))."', |
||
4939 | '".preg_replace("/'/", "\\'", get_plugin_lang('OrderStatus', 'BuyCoursesPlugin'))."', |
||
4940 | '".preg_replace("/'/", "\\'", get_plugin_lang('OrderDate', 'BuyCoursesPlugin'))."', |
||
4941 | '".preg_replace("/'/", "\\'", get_plugin_lang('PaymentMethod', 'BuyCoursesPlugin'))."', |
||
4942 | '".preg_replace("/'/", "\\'", get_plugin_lang('Price', 'BuyCoursesPlugin'))."', |
||
4943 | '".preg_replace("/'/", "\\'", get_plugin_lang('CouponDiscount', 'BuyCoursesPlugin'))."', |
||
4944 | '".preg_replace("/'/", "\\'", get_plugin_lang('Coupon', 'BuyCoursesPlugin'))."', |
||
4945 | '".preg_replace("/'/", "\\'", get_plugin_lang('ProductType', 'BuyCoursesPlugin'))."', |
||
4946 | '".preg_replace("/'/", "\\'", get_plugin_lang('Name', 'BuyCoursesPlugin'))."', |
||
4947 | '".preg_replace("/'/", "\\'", get_lang('UserName'))."', |
||
4948 | '".preg_replace("/'/", "\\'", get_lang('Email'))."',"; |
||
4949 | $model = " |
||
4950 | {name:'reference', index:'reference', height:'auto', width:70, sorttype:'string', align:'center'}, |
||
4951 | {name:'status', index:'status', height:'auto', width:70, sorttype:'string', align:'center'}, |
||
4952 | {name:'date', index:'date', height:'auto', width:70, sorttype:'date', align:'center'}, |
||
4953 | {name:'payment_type', index:'payment_type', height:'auto', width:70, sorttype:'string', align:'center'}, |
||
4954 | {name:'total_price', index:'total_price', height:'auto', width:70, sorttype:'string', align:'center'}, |
||
4955 | {name:'coupon_discount', index:'coupon_discount', height:'auto', width:40, sorttype:'string', align: 'center'}, |
||
4956 | {name:'coupon', index:'coupon', height:'auto', width:60, sorttype:'string', align:'center'}, |
||
4957 | {name:'product_type', index:'product_type', height:'auto', width:40, sorttype:'string'}, |
||
4958 | {name:'product_name', index:'product_name', height:'auto', /*width:60,*/ sorttype:'string'}, |
||
4959 | {name:'complete_user_name', index:'complete_user_name', height:'auto', width:70, sorttype:'string'}, |
||
4960 | {name:'email', index:'email', height:'auto', /*width:60,*/ sorttype:'string'}, "; |
||
4961 | if ($invoicingEnable) { |
||
4962 | $model .= "{name:'invoice', index:'invoice', height:'auto', width:70, sorttype:'string'},"; |
||
4963 | $cols .= "'".get_plugin_lang('Invoice', 'BuyCoursesPlugin')."',"; |
||
4964 | } |
||
4965 | $cols .= "'".get_lang('Options')."',"; |
||
4966 | $model .= " |
||
4967 | {name:'options', index:'options', height:'auto', width:60, sortable:false},"; |
||
4968 | $data = ''; |
||
4969 | foreach ($sales as $item) { |
||
4970 | $option = ''; |
||
4971 | if (!isset($item['complete_user_name'])) { |
||
4972 | $item['complete_user_name'] = api_get_person_name($item['firstname'], $item['lastname']); |
||
4973 | } |
||
4974 | if ($item['invoice'] == 1) { |
||
4975 | if ($invoicingEnable) { |
||
4976 | $item['invoice'] = "<a href='".api_get_path(WEB_PLUGIN_PATH).'buycourses/src/invoice.php?invoice='.$item['id']."&is_service=0" |
||
4977 | ."' title='".get_plugin_lang('InvoiceView', 'BuyCoursesPlugin')."'>". |
||
4978 | Display::return_icon('default.png', get_plugin_lang('InvoiceView', 'BuyCoursesPlugin'), '', ICON_SIZE_MEDIUM). |
||
4979 | "<br/>".$item['num_invoice']. |
||
4980 | "</a>"; |
||
4981 | } |
||
4982 | } else { |
||
4983 | $item['invoice'] = null; |
||
4984 | } |
||
4985 | if ($item['status'] == BuyCoursesPlugin::SALE_STATUS_CANCELED) { |
||
4986 | $item['status'] = get_plugin_lang('SaleStatusCanceled', 'BuyCoursesPlugin'); |
||
4987 | } elseif ($item['status'] == BuyCoursesPlugin::SALE_STATUS_PENDING) { |
||
4988 | $item['status'] = get_plugin_lang('SaleStatusPending', 'BuyCoursesPlugin'); |
||
4989 | $option = "<div class='btn-group btn-group-xs' role='group'>". |
||
4990 | "<a title='".get_plugin_lang('SubscribeUser', 'BuyCoursesPlugin')."'". |
||
4991 | " href='".api_get_self()."?order=".$item['id']."&action=confirm'". |
||
4992 | " class='btn btn-default'>". |
||
4993 | Display::return_icon('user_subscribe_session.png', get_plugin_lang('SubscribeUser', 'BuyCoursesPlugin'), '', ICON_SIZE_SMALL) |
||
4994 | ."</a>". |
||
4995 | "<a title='".get_plugin_lang('DeleteOrder', 'BuyCoursesPlugin')."'". |
||
4996 | " href='".api_get_self()."?order=".$item['id']."&action=cancel'". |
||
4997 | " class='btn btn-default'>". |
||
4998 | Display::return_icon('delete.png', get_plugin_lang('DeleteOrder', 'BuyCoursesPlugin'), '', ICON_SIZE_SMALL) |
||
4999 | ."</a>". |
||
5000 | "</div>"; |
||
5001 | } elseif ($item['status'] == BuyCoursesPlugin::SALE_STATUS_COMPLETED) { |
||
5002 | $item['status'] = get_plugin_lang('SaleStatusCompleted', 'BuyCoursesPlugin'); |
||
5003 | } |
||
5004 | $item['options'] = $option; |
||
5005 | $item['date'] = api_get_local_time($item['date']); |
||
5006 | $data .= json_encode($item).","; |
||
5007 | } |
||
5008 | |||
5009 | return " |
||
5010 | <script> |
||
5011 | $(window).load( function () { |
||
5012 | $('#table_report').jqGrid({ |
||
5013 | height: '100%', |
||
5014 | autowidth: true, |
||
5015 | LoadOnce: true, |
||
5016 | rowNum:10, |
||
5017 | rowList: [10, 25, 50, 100], |
||
5018 | pager: 'tblGridPager', |
||
5019 | datatype: 'local', |
||
5020 | viewrecords: true, |
||
5021 | gridview: true, |
||
5022 | colNames:[ $cols ], |
||
5023 | colModel:[ $model ], |
||
5024 | caption: '".get_plugin_lang('SalesReport', 'BuyCoursesPlugin')."' |
||
5025 | }); |
||
5026 | var mydata = [ $data ]; |
||
5027 | for(var i=0;i<=mydata.length;i++){ |
||
5028 | $('#table_report').jqGrid('addRowData',i+1,mydata[i]); |
||
5029 | if(i==mydata.length){ |
||
5030 | $('#table_report').trigger('reloadGrid',[{page:1}]) |
||
5031 | } |
||
5032 | } |
||
5033 | }); |
||
5034 | </script>"; |
||
5035 | } |
||
5036 | |||
5037 | /** |
||
5038 | * Filter the registered courses for show in plugin catalog. |
||
5039 | */ |
||
5040 | private function getCourses(int $first, int $maxResults) |
||
5041 | { |
||
5042 | $em = Database::getManager(); |
||
5043 | $urlId = api_get_current_access_url_id(); |
||
5044 | |||
5045 | $qb = $em->createQueryBuilder(); |
||
5046 | $qb2 = $em->createQueryBuilder(); |
||
5047 | $qb3 = $em->createQueryBuilder(); |
||
5048 | |||
5049 | $qb = $qb |
||
5050 | ->select('c') |
||
5051 | ->from('ChamiloCoreBundle:Course', 'c') |
||
5052 | ->where( |
||
5053 | $qb->expr()->notIn( |
||
5054 | 'c', |
||
5055 | $qb2 |
||
5056 | ->select('course2') |
||
5057 | ->from('ChamiloCoreBundle:SessionRelCourse', 'sc') |
||
5058 | ->join('sc.course', 'course2') |
||
5059 | ->innerJoin( |
||
5060 | 'ChamiloCoreBundle:AccessUrlRelSession', |
||
5061 | 'us', |
||
5062 | Join::WITH, |
||
5063 | 'us.sessionId = sc.session' |
||
5064 | )->where( |
||
5065 | $qb->expr()->eq('us.accessUrlId ', $urlId) |
||
5066 | ) |
||
5067 | ->getDQL() |
||
5068 | ) |
||
5069 | )->andWhere( |
||
5070 | $qb->expr()->in( |
||
5071 | 'c', |
||
5072 | $qb3 |
||
5073 | ->select('course3') |
||
5074 | ->from('ChamiloCoreBundle:AccessUrlRelCourse', 'uc') |
||
5075 | ->join('uc.course', 'course3') |
||
5076 | ->where( |
||
5077 | $qb3->expr()->eq('uc.url ', $urlId) |
||
5078 | ) |
||
5079 | ->getDQL() |
||
5080 | ) |
||
5081 | ) |
||
5082 | ->setFirstResult($first) |
||
5083 | ->setMaxResults($maxResults); |
||
5084 | |||
5085 | return $qb; |
||
5086 | } |
||
5087 | |||
5088 | /** |
||
5089 | * Get the user status for the session. |
||
5090 | * |
||
5091 | * @param int $userId The user ID |
||
5092 | * @param Session $session The session |
||
5093 | * |
||
5094 | * @return string |
||
5095 | */ |
||
5096 | private function getUserStatusForSession(int $userId, Session $session) |
||
5097 | { |
||
5098 | if (empty($userId)) { |
||
5099 | return 'NO'; |
||
5100 | } |
||
5101 | |||
5102 | $entityManager = Database::getManager(); |
||
5103 | $scuRepo = $entityManager->getRepository('ChamiloCoreBundle:SessionRelCourseRelUser'); |
||
5104 | |||
5105 | $buySaleTable = Database::get_main_table(self::TABLE_SALE); |
||
5106 | |||
5107 | // Check if user bought the course |
||
5108 | $sale = Database::select( |
||
5109 | 'COUNT(1) as qty', |
||
5110 | $buySaleTable, |
||
5111 | [ |
||
5112 | 'where' => [ |
||
5113 | 'user_id = ? AND product_type = ? AND product_id = ? AND status = ?' => [ |
||
5114 | $userId, |
||
5115 | self::PRODUCT_TYPE_SESSION, |
||
5116 | $session->getId(), |
||
5117 | self::SALE_STATUS_PENDING, |
||
5118 | ], |
||
5119 | ], |
||
5120 | ], |
||
5121 | 'first' |
||
5122 | ); |
||
5123 | |||
5124 | if ($sale['qty'] > 0) { |
||
5125 | return 'TMP'; |
||
5126 | } |
||
5127 | |||
5128 | // Check if user is already subscribe to session |
||
5129 | $userSubscription = $scuRepo->findBy([ |
||
5130 | 'session' => $session, |
||
5131 | 'user' => $userId, |
||
5132 | ]); |
||
5133 | |||
5134 | if (!empty($userSubscription)) { |
||
5135 | return 'YES'; |
||
5136 | } |
||
5137 | |||
5138 | return 'NO'; |
||
5139 | } |
||
5140 | |||
5141 | /** |
||
5142 | * Get the user status for the course. |
||
5143 | * |
||
5144 | * @param int $userId The user Id |
||
5145 | * @param Course $course The course |
||
5146 | * |
||
5147 | * @return string |
||
5148 | */ |
||
5149 | private function getUserStatusForCourse(int $userId, Course $course) |
||
5150 | { |
||
5151 | if (empty($userId)) { |
||
5152 | return 'NO'; |
||
5153 | } |
||
5154 | |||
5155 | $entityManager = Database::getManager(); |
||
5156 | $cuRepo = $entityManager->getRepository('ChamiloCoreBundle:CourseRelUser'); |
||
5157 | $buySaleTable = Database::get_main_table(self::TABLE_SALE); |
||
5158 | |||
5159 | // Check if user bought the course |
||
5160 | $sale = Database::select( |
||
5161 | 'COUNT(1) as qty', |
||
5162 | $buySaleTable, |
||
5163 | [ |
||
5164 | 'where' => [ |
||
5165 | 'user_id = ? AND product_type = ? AND product_id = ? AND status = ?' => [ |
||
5166 | $userId, |
||
5167 | self::PRODUCT_TYPE_COURSE, |
||
5168 | $course->getId(), |
||
5169 | self::SALE_STATUS_PENDING, |
||
5170 | ], |
||
5171 | ], |
||
5172 | ], |
||
5173 | 'first' |
||
5174 | ); |
||
5175 | |||
5176 | if ($sale['qty'] > 0) { |
||
5177 | return 'TMP'; |
||
5178 | } |
||
5179 | |||
5180 | // Check if user is already subscribe to course |
||
5181 | $userSubscription = $cuRepo->findBy([ |
||
5182 | 'course' => $course, |
||
5183 | 'user' => $userId, |
||
5184 | ]); |
||
5185 | |||
5186 | if (!empty($userSubscription)) { |
||
5187 | return 'YES'; |
||
5188 | } |
||
5189 | |||
5190 | return 'NO'; |
||
5191 | } |
||
5192 | |||
5193 | /** |
||
5194 | * Update the sale status. |
||
5195 | * |
||
5196 | * @param int $saleId The sale ID |
||
5197 | * @param int $newStatus The new status |
||
5198 | * |
||
5199 | * @return bool |
||
5200 | */ |
||
5201 | private function updateSaleStatus(int $saleId, int $newStatus = self::SALE_STATUS_PENDING) |
||
5202 | { |
||
5203 | $saleTable = Database::get_main_table(self::TABLE_SALE); |
||
5204 | |||
5205 | return Database::update( |
||
5206 | $saleTable, |
||
5207 | ['status' => (int) $newStatus], |
||
5208 | ['id = ?' => (int) $saleId] |
||
5209 | ); |
||
5210 | } |
||
5211 | |||
5212 | /** |
||
5213 | * Search filtered sessions by name, and range of price. |
||
5214 | * |
||
5215 | * @param string $name Optional. The name filter |
||
5216 | * @param int $min Optional. The minimum price filter |
||
5217 | * @param int $max Optional. The maximum price filter |
||
5218 | * @param string $typeResult Optional. 'all' and 'count' |
||
5219 | * @param int $sessionCategory Optional. Session category id |
||
5220 | * |
||
5221 | * @return array |
||
5222 | */ |
||
5223 | private function filterSessionList( |
||
5224 | int $start, |
||
5225 | int $end, |
||
5226 | string $name = null, |
||
5227 | int $min = 0, |
||
5228 | int $max = 0, |
||
5229 | string $typeResult = 'all', |
||
5230 | int $sessionCategory = 0 |
||
5231 | ) { |
||
5232 | $itemTable = Database::get_main_table(self::TABLE_ITEM); |
||
5233 | $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION); |
||
5234 | |||
5235 | $innerJoin = "$itemTable i ON s.id = i.product_id"; |
||
5236 | $whereConditions = [ |
||
5237 | 'i.product_type = ? ' => self::PRODUCT_TYPE_SESSION, |
||
5238 | ]; |
||
5239 | |||
5240 | if (!empty($name)) { |
||
5241 | $whereConditions['AND s.name LIKE %?%'] = $name; |
||
5242 | } |
||
5243 | |||
5244 | if (!empty($min)) { |
||
5245 | $whereConditions['AND i.price >= ?'] = $min; |
||
5246 | } |
||
5247 | |||
5248 | if (!empty($max)) { |
||
5249 | $whereConditions['AND i.price <= ?'] = $max; |
||
5250 | } |
||
5251 | |||
5252 | if ($sessionCategory != 0) { |
||
5253 | $whereConditions['AND s.session_category_id = ?'] = $sessionCategory; |
||
5254 | } |
||
5255 | |||
5256 | $sessionIds = Database::select( |
||
5257 | 's.id', |
||
5258 | "$sessionTable s INNER JOIN $innerJoin", |
||
5259 | ['where' => $whereConditions, 'limit' => "$start, $end"], |
||
5260 | $typeResult |
||
5261 | ); |
||
5262 | |||
5263 | if ($typeResult === 'count') { |
||
5264 | return $sessionIds; |
||
5265 | } |
||
5266 | |||
5267 | if (!$sessionIds) { |
||
5268 | return []; |
||
5269 | } |
||
5270 | |||
5271 | $sessions = []; |
||
5272 | |||
5273 | foreach ($sessionIds as $sessionId) { |
||
5274 | $sessions[] = Database::getManager()->find( |
||
5275 | 'ChamiloCoreBundle:Session', |
||
5276 | $sessionId |
||
5277 | ); |
||
5278 | } |
||
5279 | |||
5280 | return $sessions; |
||
5281 | } |
||
5282 | |||
5283 | /** |
||
5284 | * Search filtered courses by name, and range of price. |
||
5285 | * |
||
5286 | * @param string $name Optional. The name filter |
||
5287 | * @param int $min Optional. The minimun price filter |
||
5288 | * @param int $max Optional. The maximum price filter |
||
5289 | * |
||
5290 | * @return array |
||
5291 | */ |
||
5292 | private function filterCourseList( |
||
5293 | int $start, |
||
5294 | int $end, |
||
5295 | string $name = null, |
||
5296 | int $min = 0, |
||
5297 | int $max = 0, |
||
5298 | string $typeResult = 'all' |
||
5299 | ) { |
||
5300 | $itemTable = Database::get_main_table(self::TABLE_ITEM); |
||
5301 | $courseTable = Database::get_main_table(TABLE_MAIN_COURSE); |
||
5302 | $urlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE); |
||
5303 | |||
5304 | $urlId = api_get_current_access_url_id(); |
||
5305 | |||
5306 | $min = floatval($min); |
||
5307 | $max = floatval($max); |
||
5308 | |||
5309 | $whereConditions = [ |
||
5310 | 'i.product_type = ? ' => self::PRODUCT_TYPE_COURSE, |
||
5311 | ]; |
||
5312 | |||
5313 | if (!empty($name)) { |
||
5314 | $whereConditions['AND c.title LIKE %?%'] = $name; |
||
5315 | } |
||
5316 | |||
5317 | if (!empty($min)) { |
||
5318 | $whereConditions['AND i.price >= ?'] = $min; |
||
5319 | } |
||
5320 | |||
5321 | if (!empty($max)) { |
||
5322 | $whereConditions['AND i.price <= ?'] = $max; |
||
5323 | } |
||
5324 | |||
5325 | $whereConditions['AND url.access_url_id = ?'] = $urlId; |
||
5326 | |||
5327 | $courseIds = Database::select( |
||
5328 | 'c.id', |
||
5329 | "$courseTable c |
||
5330 | INNER JOIN $itemTable i |
||
5331 | ON c.id = i.product_id |
||
5332 | INNER JOIN $urlTable url |
||
5333 | ON c.id = url.c_id |
||
5334 | ", |
||
5335 | ['where' => $whereConditions, 'limit' => "$start, $end"], |
||
5336 | $typeResult |
||
5337 | ); |
||
5338 | |||
5339 | if ($typeResult === 'count') { |
||
5340 | return $courseIds; |
||
5341 | } |
||
5342 | |||
5343 | if (!$courseIds) { |
||
5344 | return []; |
||
5345 | } |
||
5346 | |||
5347 | $courses = []; |
||
5348 | foreach ($courseIds as $courseId) { |
||
5349 | $courses[] = Database::getManager()->find( |
||
5350 | 'ChamiloCoreBundle:Course', |
||
5351 | $courseId |
||
5352 | ); |
||
5353 | } |
||
5354 | |||
5355 | return $courses; |
||
5356 | } |
||
5357 | |||
5358 | /** |
||
5359 | * Search filtered sessions by name, and range of price. |
||
5360 | * |
||
5361 | * @param string $name Optional. The name filter |
||
5362 | * @param int $sessionCategory Optional. Session category id |
||
5363 | * |
||
5364 | * @return array |
||
5365 | */ |
||
5366 | private function filterSubscriptionSessionList( |
||
5367 | int $start, |
||
5368 | int $end, |
||
5369 | string $name = null, |
||
5370 | string $typeResult = 'all', |
||
5371 | int $sessionCategory = 0 |
||
5372 | ) { |
||
5373 | $subscriptionTable = Database::get_main_table(self::TABLE_SUBSCRIPTION); |
||
5374 | $sessionTable = Database::get_main_table(TABLE_MAIN_SESSION); |
||
5375 | |||
5376 | $innerJoin = "$subscriptionTable st ON s.id = st.product_id"; |
||
5377 | $whereConditions = [ |
||
5378 | 'st.product_type = ? ' => self::PRODUCT_TYPE_SESSION, |
||
5379 | ]; |
||
5380 | |||
5381 | if (!empty($name)) { |
||
5382 | $whereConditions['AND s.name LIKE %?%'] = $name; |
||
5383 | } |
||
5384 | |||
5385 | if ($sessionCategory != 0) { |
||
5386 | $whereConditions['AND s.session_category_id = ?'] = $sessionCategory; |
||
5387 | } |
||
5388 | |||
5389 | $sessionIds = Database::select( |
||
5390 | 'DISTINCT s.id', |
||
5391 | "$sessionTable s INNER JOIN $innerJoin", |
||
5392 | ['where' => $whereConditions, 'limit' => "$start, $end"], |
||
5393 | $typeResult |
||
5394 | ); |
||
5395 | |||
5396 | if ($typeResult === 'count') { |
||
5397 | return $sessionIds; |
||
5398 | } |
||
5399 | |||
5400 | if (!$sessionIds) { |
||
5401 | return []; |
||
5402 | } |
||
5403 | |||
5404 | $sessions = []; |
||
5405 | |||
5406 | foreach ($sessionIds as $sessionId) { |
||
5407 | $sessions[] = Database::getManager()->find( |
||
5408 | 'ChamiloCoreBundle:Session', |
||
5409 | $sessionId |
||
5410 | ); |
||
5411 | } |
||
5412 | |||
5413 | return $sessions; |
||
5414 | } |
||
5415 | |||
5416 | /** |
||
5417 | * Search filtered subscriptions courses by name, and range of price. |
||
5418 | * |
||
5419 | * @param string $name Optional. The name filter |
||
5420 | * |
||
5421 | * @return array |
||
5422 | */ |
||
5423 | private function filterSubscriptionCourseList( |
||
5424 | int $start, |
||
5425 | int $end, |
||
5426 | string $name = '', |
||
5427 | string $typeResult = 'all' |
||
5428 | ) { |
||
5429 | $subscriptionTable = Database::get_main_table(self::TABLE_SUBSCRIPTION); |
||
5430 | $courseTable = Database::get_main_table(TABLE_MAIN_COURSE); |
||
5431 | $urlTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE); |
||
5432 | |||
5433 | $urlId = api_get_current_access_url_id(); |
||
5434 | |||
5435 | $whereConditions = [ |
||
5436 | 'st.product_type = ? ' => self::PRODUCT_TYPE_COURSE, |
||
5437 | ]; |
||
5438 | |||
5439 | if (!empty($name)) { |
||
5440 | $whereConditions['AND c.title LIKE %?%'] = $name; |
||
5441 | } |
||
5442 | |||
5443 | $whereConditions['AND url.access_url_id = ?'] = $urlId; |
||
5444 | |||
5445 | $courseIds = Database::select( |
||
5446 | 'DISTINCT c.id', |
||
5447 | "$courseTable c |
||
5448 | INNER JOIN $subscriptionTable st |
||
5449 | ON c.id = st.product_id |
||
5450 | INNER JOIN $urlTable url |
||
5451 | ON c.id = url.c_id |
||
5452 | ", |
||
5453 | ['where' => $whereConditions, 'limit' => "$start, $end"], |
||
5454 | $typeResult |
||
5455 | ); |
||
5456 | |||
5457 | if ($typeResult === 'count') { |
||
5458 | return $courseIds; |
||
5459 | } |
||
5460 | |||
5461 | if (!$courseIds) { |
||
5462 | return []; |
||
5463 | } |
||
5464 | |||
5465 | $courses = []; |
||
5466 | foreach ($courseIds as $courseId) { |
||
5467 | $courses[] = Database::getManager()->find( |
||
5468 | 'ChamiloCoreBundle:Course', |
||
5469 | $courseId |
||
5470 | ); |
||
5471 | } |
||
5472 | |||
5473 | return $courses; |
||
5474 | } |
||
5475 | |||
5476 | /** |
||
5477 | * Update the service sale status. |
||
5478 | * |
||
5479 | * @param int $serviceSaleId The service sale ID |
||
5480 | * @param int $newStatus The new status |
||
5481 | * |
||
5482 | * @return bool |
||
5483 | */ |
||
5484 | private function updateServiceSaleStatus( |
||
5485 | int $serviceSaleId, |
||
5486 | int $newStatus = self::SERVICE_STATUS_PENDING |
||
5487 | ) { |
||
5488 | $serviceSaleTable = Database::get_main_table(self::TABLE_SERVICES_SALE); |
||
5489 | |||
5490 | return Database::update( |
||
5491 | $serviceSaleTable, |
||
5492 | ['status' => $newStatus], |
||
5493 | ['id = ?' => $serviceSaleId] |
||
5494 | ); |
||
5495 | } |
||
5496 | |||
5497 | /** |
||
5498 | * Get the items (courses or sessions) of a coupon. |
||
5499 | * |
||
5500 | * @return array The item data |
||
5501 | */ |
||
5502 | private function getItemsCoupons(int $couponId, int $productType) |
||
5503 | { |
||
5504 | $couponItemTable = Database::get_main_table(self::TABLE_COUPON_ITEM); |
||
5505 | |||
5506 | if ($productType == self::PRODUCT_TYPE_COURSE) { |
||
5507 | $itemTable = Database::get_main_table(TABLE_MAIN_COURSE); |
||
5508 | $select = ['ci.product_id as id', 'it.title']; |
||
5509 | } elseif ($productType == self::PRODUCT_TYPE_SESSION) { |
||
5510 | $itemTable = Database::get_main_table(TABLE_MAIN_SESSION); |
||
5511 | $select = ['ci.product_id as id', 'it.name']; |
||
5512 | } |
||
5513 | |||
5514 | $couponFrom = " |
||
5515 | $couponItemTable ci |
||
5516 | INNER JOIN $itemTable it |
||
5517 | on it.id = ci.product_id and ci.product_type = $productType |
||
5518 | "; |
||
5519 | |||
5520 | return Database::select( |
||
5521 | $select, |
||
5522 | $couponFrom, |
||
5523 | [ |
||
5524 | 'where' => [ |
||
5525 | 'ci.coupon_id = ? ' => $couponId, |
||
5526 | ], |
||
5527 | ] |
||
5528 | ); |
||
5529 | } |
||
5530 | |||
5531 | /** |
||
5532 | * Get the services of a coupon. |
||
5533 | * |
||
5534 | * @param int $couponId The coupon ID |
||
5535 | * |
||
5536 | * @return array The service data |
||
5537 | */ |
||
5538 | private function getServicesCoupons(int $couponId) |
||
5539 | { |
||
5540 | $couponServiceTable = Database::get_main_table(self::TABLE_COUPON_SERVICE); |
||
5541 | $serviceTable = Database::get_main_table(self::TABLE_SERVICES); |
||
5542 | |||
5543 | $couponFrom = " |
||
5544 | $couponServiceTable cs |
||
5545 | INNER JOIN $serviceTable s |
||
5546 | on s.id = cs.service_id |
||
5547 | "; |
||
5548 | |||
5549 | return Database::select( |
||
5550 | ['cs.service_id as id', 's.name'], |
||
5551 | $couponFrom, |
||
5552 | [ |
||
5553 | 'where' => [ |
||
5554 | 'cs.coupon_id = ? ' => $couponId, |
||
5555 | ], |
||
5556 | ] |
||
5557 | ); |
||
5558 | } |
||
5559 | |||
5560 | /** |
||
5561 | * Get an array of coupons filtered by their status. |
||
5562 | * |
||
5563 | * @param int $status The coupon activation status |
||
5564 | * |
||
5565 | * @return array Coupons data |
||
5566 | */ |
||
5567 | private function getDataCoupons(int $status = null) |
||
5568 | { |
||
5569 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
5570 | |||
5571 | if ($status != null) { |
||
5572 | return Database::select( |
||
5573 | ['*'], |
||
5574 | $couponTable, |
||
5575 | [ |
||
5576 | 'where' => [ |
||
5577 | ' active = ? ' => (int) $status, |
||
5578 | ], |
||
5579 | 'order' => 'id DESC', |
||
5580 | ] |
||
5581 | ); |
||
5582 | } else { |
||
5583 | return Database::select( |
||
5584 | ['*'], |
||
5585 | $couponTable, |
||
5586 | [ |
||
5587 | 'order' => 'id DESC', |
||
5588 | ] |
||
5589 | ); |
||
5590 | } |
||
5591 | } |
||
5592 | |||
5593 | /** |
||
5594 | * Get data of a coupon for a product (course or service) by the coupon ID. |
||
5595 | * |
||
5596 | * @param int $couponId The coupon code code |
||
5597 | * @param int $productType The product type |
||
5598 | * @param int $productId The product ID |
||
5599 | * |
||
5600 | * @return array The coupon data |
||
5601 | */ |
||
5602 | private function getDataCoupon(int $couponId, int $productType = null, int $productId = null) |
||
5603 | { |
||
5604 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
5605 | |||
5606 | if ($productType == null || $productId == null) { |
||
5607 | return Database::select( |
||
5608 | ['*'], |
||
5609 | $couponTable, |
||
5610 | [ |
||
5611 | 'where' => [ |
||
5612 | 'id = ? ' => $couponId, |
||
5613 | ], |
||
5614 | ], |
||
5615 | 'first' |
||
5616 | ); |
||
5617 | } else { |
||
5618 | $couponItemTable = Database::get_main_table(self::TABLE_COUPON_ITEM); |
||
5619 | $dtmNow = api_get_utc_datetime(); |
||
5620 | |||
5621 | $couponFrom = " |
||
5622 | $couponTable c |
||
5623 | INNER JOIN $couponItemTable ci |
||
5624 | on ci.coupon_id = c.id |
||
5625 | "; |
||
5626 | |||
5627 | return Database::select( |
||
5628 | ['c.*'], |
||
5629 | $couponFrom, |
||
5630 | [ |
||
5631 | 'where' => [ |
||
5632 | 'c.id = ? AND ' => $couponId, |
||
5633 | 'c.valid_start <= ? AND ' => $dtmNow, |
||
5634 | 'c.valid_end >= ? AND ' => $dtmNow, |
||
5635 | 'ci.product_type = ? AND ' => $productType, |
||
5636 | 'ci.product_id = ?' => $productId, |
||
5637 | ], |
||
5638 | ], |
||
5639 | 'first' |
||
5640 | ); |
||
5641 | } |
||
5642 | } |
||
5643 | |||
5644 | /** |
||
5645 | * Get data of a coupon for a product (course or service) by the coupon code. |
||
5646 | * |
||
5647 | * @param string $couponCode The coupon code code |
||
5648 | * @param int $productType The product type |
||
5649 | * @param int $productId The product ID |
||
5650 | * |
||
5651 | * @return array The coupon data |
||
5652 | */ |
||
5653 | private function getDataCouponByCode(string $couponCode, int $productType = null, int $productId = null) |
||
5654 | { |
||
5655 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
5656 | $couponItemTable = Database::get_main_table(self::TABLE_COUPON_ITEM); |
||
5657 | $dtmNow = api_get_utc_datetime(); |
||
5658 | |||
5659 | if ($productType == null || $productId == null) { |
||
5660 | return Database::select( |
||
5661 | ['*'], |
||
5662 | $couponTable, |
||
5663 | [ |
||
5664 | 'where' => [ |
||
5665 | 'code = ? ' => $couponCode, |
||
5666 | ], |
||
5667 | ], |
||
5668 | 'first' |
||
5669 | ); |
||
5670 | } else { |
||
5671 | $couponFrom = " |
||
5672 | $couponTable c |
||
5673 | INNER JOIN $couponItemTable ci |
||
5674 | on ci.coupon_id = c.id |
||
5675 | "; |
||
5676 | |||
5677 | return Database::select( |
||
5678 | ['c.*'], |
||
5679 | $couponFrom, |
||
5680 | [ |
||
5681 | 'where' => [ |
||
5682 | 'c.code = ? AND ' => $couponCode, |
||
5683 | 'c.valid_start <= ? AND ' => $dtmNow, |
||
5684 | 'c.valid_end >= ? AND ' => $dtmNow, |
||
5685 | 'ci.product_type = ? AND ' => $productType, |
||
5686 | 'ci.product_id = ?' => $productId, |
||
5687 | ], |
||
5688 | ], |
||
5689 | 'first' |
||
5690 | ); |
||
5691 | } |
||
5692 | } |
||
5693 | |||
5694 | /** |
||
5695 | * Get data of a coupon for a service by the coupon ID. |
||
5696 | * |
||
5697 | * @param int $couponId The coupon ID |
||
5698 | * @param int $serviceId The service ID |
||
5699 | * |
||
5700 | * @return array The coupon data |
||
5701 | */ |
||
5702 | private function getDataCouponService(int $couponId, int $serviceId) |
||
5703 | { |
||
5704 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
5705 | $couponServiceTable = Database::get_main_table(self::TABLE_COUPON_SERVICE); |
||
5706 | $dtmNow = api_get_utc_datetime(); |
||
5707 | |||
5708 | $couponFrom = " |
||
5709 | $couponTable c |
||
5710 | INNER JOIN $couponServiceTable cs |
||
5711 | on cs.coupon_id = c.id |
||
5712 | "; |
||
5713 | |||
5714 | return Database::select( |
||
5715 | ['c.*'], |
||
5716 | $couponFrom, |
||
5717 | [ |
||
5718 | 'where' => [ |
||
5719 | 'c.id = ? AND ' => $couponId, |
||
5720 | 'c.valid_start <= ? AND ' => $dtmNow, |
||
5721 | 'c.valid_end >= ? AND ' => $dtmNow, |
||
5722 | 'cs.service_id = ?' => $serviceId, |
||
5723 | ], |
||
5724 | ], |
||
5725 | 'first' |
||
5726 | ); |
||
5727 | } |
||
5728 | |||
5729 | /** |
||
5730 | * Get data of coupon for a service by the coupon code. |
||
5731 | * |
||
5732 | * @param string $couponCode The coupon code |
||
5733 | * @param int $serviceId The service ID |
||
5734 | * |
||
5735 | * @return array The coupon data |
||
5736 | */ |
||
5737 | private function getDataCouponServiceByCode(string $couponCode, int $serviceId) |
||
5738 | { |
||
5739 | $couponTable = Database::get_main_table(self::TABLE_COUPON); |
||
5740 | $couponServiceTable = Database::get_main_table(self::TABLE_COUPON_SERVICE); |
||
5741 | $dtmNow = api_get_utc_datetime(); |
||
5742 | |||
5743 | $couponFrom = " |
||
5744 | $couponTable c |
||
5745 | INNER JOIN $couponServiceTable cs |
||
5746 | on cs.coupon_id = c.id |
||
5747 | "; |
||
5748 | |||
5749 | return Database::select( |
||
5750 | ['c.*'], |
||
5751 | $couponFrom, |
||
5752 | [ |
||
5753 | 'where' => [ |
||
5754 | 'c.code = ? AND ' => $couponCode, |
||
5755 | 'c.valid_start <= ? AND ' => $dtmNow, |
||
5756 | 'c.valid_end >= ? AND ' => $dtmNow, |
||
5757 | 'cs.service_id = ?' => $serviceId, |
||
5758 | ], |
||
5759 | ], |
||
5760 | 'first' |
||
5761 | ); |
||
5762 | } |
||
5763 | |||
5764 | /** |
||
5765 | * Update a coupon. |
||
5766 | * |
||
5767 | * @return int |
||
5768 | */ |
||
5769 | private function updateCoupon(array $coupon) |
||
5770 | { |
||
5771 | $couponExist = $this->getCouponByCode($coupon['code']); |
||
5772 | if (!$couponExist) { |
||
5773 | Display::addFlash( |
||
5774 | Display::return_message( |
||
5775 | $this->get_lang('CouponNoExists'), |
||
5776 | 'error', |
||
5777 | false |
||
5778 | ) |
||
5779 | ); |
||
5780 | |||
5781 | return false; |
||
5782 | } |
||
5783 | |||
5784 | $values = [ |
||
5785 | 'valid_start' => $coupon['valid_start'], |
||
5786 | 'valid_end' => $coupon['valid_end'], |
||
5787 | 'active' => $coupon['active'], |
||
5788 | ]; |
||
5789 | |||
5790 | return Database::update( |
||
5791 | self::TABLE_COUPON, |
||
5792 | $values, |
||
5793 | ['id = ?' => $coupon['id']] |
||
5794 | ); |
||
5795 | } |
||
5796 | |||
5797 | /** |
||
5798 | * Register a coupon. |
||
5799 | * |
||
5800 | * @return int |
||
5801 | */ |
||
5802 | private function registerCoupon(array $coupon) |
||
5803 | { |
||
5804 | $couponExist = $this->getCouponByCode($coupon['code']); |
||
5805 | if ($couponExist) { |
||
5806 | Display::addFlash( |
||
5807 | Display::return_message( |
||
5808 | $this->get_lang('CouponCodeUsed'), |
||
5809 | 'error', |
||
5810 | false |
||
5811 | ) |
||
5812 | ); |
||
5813 | |||
5814 | return false; |
||
5815 | } |
||
5816 | |||
5817 | $values = [ |
||
5818 | 'code' => (string) $coupon['code'], |
||
5819 | 'discount_type' => (int) $coupon['discount_type'], |
||
5820 | 'discount_amount' => $coupon['discount_amount'], |
||
5821 | 'valid_start' => $coupon['valid_start'], |
||
5822 | 'valid_end' => $coupon['valid_end'], |
||
5823 | 'delivered' => 0, |
||
5824 | 'active' => $coupon['active'], |
||
5825 | ]; |
||
5826 | |||
5827 | return Database::insert(self::TABLE_COUPON, $values); |
||
5828 | } |
||
5829 | |||
5830 | /** |
||
5831 | * Register a coupon item. |
||
5832 | * |
||
5833 | * @param int $couponId The coupon ID |
||
5834 | * @param int $productType The product type |
||
5835 | * @param int $productId The product ID |
||
5836 | * |
||
5837 | * @return int |
||
5838 | */ |
||
5839 | private function registerCouponItem(int $couponId, int $productType, int $productId) |
||
5840 | { |
||
5841 | $coupon = $this->getDataCoupon($couponId); |
||
5842 | if (empty($coupon)) { |
||
5843 | Display::addFlash( |
||
5844 | Display::return_message( |
||
5845 | $this->get_lang('CouponNoExists'), |
||
5846 | 'error', |
||
5847 | false |
||
5848 | ) |
||
5849 | ); |
||
5850 | |||
5851 | return false; |
||
5852 | } |
||
5853 | |||
5854 | $values = [ |
||
5855 | 'coupon_id' => $couponId, |
||
5856 | 'product_type' => $productType, |
||
5857 | 'product_id' => $productId, |
||
5858 | ]; |
||
5859 | |||
5860 | return Database::insert(self::TABLE_COUPON_ITEM, $values); |
||
5861 | } |
||
5862 | |||
5863 | /** |
||
5864 | * Remove all coupon items for a product type and coupon ID. |
||
5865 | * |
||
5866 | * @param int $productType The product type |
||
5867 | * @param int $couponId The coupon ID |
||
5868 | * |
||
5869 | * @return int Rows affected. Otherwise return false |
||
5870 | */ |
||
5871 | private function deleteCouponItemsByCoupon(int $productType, int $couponId) |
||
5872 | { |
||
5873 | return Database::delete( |
||
5874 | Database::get_main_table(self::TABLE_COUPON_ITEM), |
||
5875 | [ |
||
5876 | 'product_type = ? AND ' => $productType, |
||
5877 | 'coupon_id = ?' => $couponId, |
||
5878 | ] |
||
5879 | ); |
||
5880 | } |
||
5881 | |||
5882 | /** |
||
5883 | * Register a coupon service. |
||
5884 | * |
||
5885 | * @param int $couponId The coupon ID |
||
5886 | * @param int $serviceId The service ID |
||
5887 | * |
||
5888 | * @return int |
||
5889 | */ |
||
5890 | private function registerCouponService(int $couponId, int $serviceId) |
||
5891 | { |
||
5892 | $coupon = $this->getDataCoupon($couponId); |
||
5893 | if (empty($coupon)) { |
||
5894 | Display::addFlash( |
||
5895 | Display::return_message( |
||
5896 | $this->get_lang('CouponNoExists'), |
||
5897 | 'error', |
||
5898 | false |
||
5899 | ) |
||
5900 | ); |
||
5901 | |||
5902 | return false; |
||
5903 | } |
||
5904 | |||
5905 | $values = [ |
||
5906 | 'coupon_id' => $couponId, |
||
5907 | 'service_id' => $serviceId, |
||
5908 | ]; |
||
5909 | |||
5910 | return Database::insert(self::TABLE_COUPON_SERVICE, $values); |
||
5911 | } |
||
5912 | |||
5913 | /** |
||
5914 | * Remove all coupon services for a product type and coupon ID. |
||
5915 | * |
||
5916 | * @return int Rows affected. Otherwise, return false |
||
5917 | */ |
||
5918 | private function deleteCouponServicesByCoupon(int $couponId) |
||
5919 | { |
||
5920 | return Database::delete( |
||
5921 | Database::get_main_table(self::TABLE_COUPON_SERVICE), |
||
5922 | [ |
||
5923 | 'coupon_id = ?' => (int) $couponId, |
||
5924 | ] |
||
5925 | ); |
||
5926 | } |
||
5927 | |||
5928 | /** |
||
5929 | * Get an array of subscriptions. |
||
5930 | * |
||
5931 | * @return array Subscriptions data |
||
5932 | */ |
||
5933 | private function getDataSubscriptions(int $productType, int $productId) |
||
5934 | { |
||
5935 | $subscriptionTable = Database::get_main_table(self::TABLE_SUBSCRIPTION); |
||
5936 | |||
5937 | return Database::select( |
||
5938 | ['*'], |
||
5939 | $subscriptionTable, |
||
5940 | [ |
||
5941 | 'where' => [ |
||
5942 | 'product_type = ? AND ' => (int) $productType, |
||
5943 | 'product_id = ? ' => (int) $productId, |
||
5944 | ], |
||
5945 | 'order' => 'duration ASC', |
||
5946 | ] |
||
5947 | ); |
||
5948 | } |
||
5949 | |||
5950 | /** |
||
5951 | * Get data of a subscription for a product (course or service) by the subscription ID. |
||
5952 | * |
||
5953 | * @param int $productType The product type |
||
5954 | * @param int $productId The product ID |
||
5955 | * @param int $duration The duration (in seconds) |
||
5956 | * |
||
5957 | * @return array The subscription data |
||
5958 | */ |
||
5959 | private function getDataSubscription(int $productType, int $productId, int $duration) |
||
5960 | { |
||
5961 | $subscriptionTable = Database::get_main_table(self::TABLE_SUBSCRIPTION); |
||
5962 | |||
5963 | return Database::select( |
||
5964 | ['*'], |
||
5965 | $subscriptionTable, |
||
5966 | [ |
||
5967 | 'where' => [ |
||
5968 | 'product_type = ? AND ' => $productType, |
||
5969 | 'product_id = ? AND ' => $productId, |
||
5970 | 'duration = ? ' => $duration, |
||
5971 | ], |
||
5972 | ], |
||
5973 | 'first' |
||
5974 | ); |
||
5975 | } |
||
5976 | |||
5977 | /** |
||
5978 | * Update a subscription. |
||
5979 | * |
||
5980 | * @return int |
||
5981 | */ |
||
5982 | private function updateSubscription(int $productType, int $productId, int $taxPerc) |
||
5983 | { |
||
5984 | $values = [ |
||
5985 | 'tax_perc' => $taxPerc, |
||
5986 | ]; |
||
5987 | |||
5988 | return Database::update( |
||
5989 | self::TABLE_SUBSCRIPTION, |
||
5990 | $values, |
||
5991 | [ |
||
5992 | 'product_type = ? AND ' => $productType, |
||
5993 | 'product_id = ?' => $productId, |
||
5994 | ] |
||
5995 | ); |
||
5996 | |||
5997 | return true; |
||
0 ignored issues
–
show
|
|||
5998 | } |
||
5999 | |||
6000 | /** |
||
6001 | * Register a subscription. |
||
6002 | * |
||
6003 | * @return int |
||
6004 | */ |
||
6005 | private function registerSubscription(array $subscription, array $frequency) |
||
6006 | { |
||
6007 | $values = [ |
||
6008 | 'product_type' => (int) $subscription['product_type'], |
||
6009 | 'product_id' => (int) $subscription['product_id'], |
||
6010 | 'duration' => (int) $frequency['duration'], |
||
6011 | 'currency_id' => (int) $subscription['currency_id'], |
||
6012 | 'tax_perc' => (int) $subscription['tax_perc'], |
||
6013 | 'price' => (float) $frequency['price'], |
||
6014 | ]; |
||
6015 | |||
6016 | Database::insert(self::TABLE_SUBSCRIPTION, $values); |
||
6017 | |||
6018 | return true; |
||
6019 | } |
||
6020 | |||
6021 | /** |
||
6022 | * Update the subscription sale status. |
||
6023 | * |
||
6024 | * @param int $saleId The sale ID |
||
6025 | * @param int $newStatus The new status |
||
6026 | * |
||
6027 | * @return bool |
||
6028 | */ |
||
6029 | private function updateSubscriptionSaleStatus(int $saleId, int $newStatus = self::SALE_STATUS_PENDING) |
||
6030 | { |
||
6031 | $saleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
6032 | |||
6033 | return Database::update( |
||
6034 | $saleTable, |
||
6035 | ['status' => $newStatus], |
||
6036 | ['id = ?' => $saleId] |
||
6037 | ); |
||
6038 | } |
||
6039 | |||
6040 | /** |
||
6041 | * Get the user status for the subscription session. |
||
6042 | * |
||
6043 | * @param int $userId The user ID |
||
6044 | * @param Session $session The session |
||
6045 | * |
||
6046 | * @return string |
||
6047 | */ |
||
6048 | private function getUserStatusForSubscriptionSession(int $userId, Session $session) |
||
6049 | { |
||
6050 | if (empty($userId)) { |
||
6051 | return 'NO'; |
||
6052 | } |
||
6053 | |||
6054 | $entityManager = Database::getManager(); |
||
6055 | $scuRepo = $entityManager->getRepository('ChamiloCoreBundle:SessionRelCourseRelUser'); |
||
6056 | |||
6057 | $buySaleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
6058 | |||
6059 | // Check if user bought the course |
||
6060 | $sale = Database::select( |
||
6061 | 'COUNT(1) as qty', |
||
6062 | $buySaleTable, |
||
6063 | [ |
||
6064 | 'where' => [ |
||
6065 | 'user_id = ? AND product_type = ? AND product_id = ? AND status = ? AND (expired is NULL OR expired <> ?)' => [ |
||
6066 | $userId, |
||
6067 | self::PRODUCT_TYPE_SESSION, |
||
6068 | $session->getId(), |
||
6069 | self::SALE_STATUS_PENDING, |
||
6070 | 1, |
||
6071 | ], |
||
6072 | ], |
||
6073 | ], |
||
6074 | 'first' |
||
6075 | ); |
||
6076 | |||
6077 | if ($sale['qty'] > 0) { |
||
6078 | return 'TMP'; |
||
6079 | } |
||
6080 | |||
6081 | // Check if user is already subscribe to session |
||
6082 | $userSubscription = $scuRepo->findBy([ |
||
6083 | 'session' => $session, |
||
6084 | 'user' => $userId, |
||
6085 | ]); |
||
6086 | |||
6087 | if (!empty($userSubscription)) { |
||
6088 | return 'YES'; |
||
6089 | } |
||
6090 | |||
6091 | return 'NO'; |
||
6092 | } |
||
6093 | |||
6094 | /** |
||
6095 | * Get the user status for the subscription course. |
||
6096 | * |
||
6097 | * @param int $userId The user Id |
||
6098 | * @param Course $course The course |
||
6099 | * |
||
6100 | * @return string |
||
6101 | */ |
||
6102 | private function getUserStatusForSubscriptionCourse(int $userId, Course $course) |
||
6103 | { |
||
6104 | if (empty($userId)) { |
||
6105 | return 'NO'; |
||
6106 | } |
||
6107 | |||
6108 | $entityManager = Database::getManager(); |
||
6109 | $cuRepo = $entityManager->getRepository('ChamiloCoreBundle:CourseRelUser'); |
||
6110 | $buySaleTable = Database::get_main_table(self::TABLE_SUBSCRIPTION_SALE); |
||
6111 | |||
6112 | // Check if user bought the course |
||
6113 | $sale = Database::select( |
||
6114 | 'COUNT(1) as qty', |
||
6115 | $buySaleTable, |
||
6116 | [ |
||
6117 | 'where' => [ |
||
6118 | 'user_id = ? AND product_type = ? AND product_id = ? AND status = ? AND (expired is NULL OR expired <> ?)' => [ |
||
6119 | $userId, |
||
6120 | self::PRODUCT_TYPE_COURSE, |
||
6121 | $course->getId(), |
||
6122 | self::SALE_STATUS_PENDING, |
||
6123 | 1, |
||
6124 | ], |
||
6125 | ], |
||
6126 | ], |
||
6127 | 'first' |
||
6128 | ); |
||
6129 | |||
6130 | if ($sale['qty'] > 0) { |
||
6131 | return 'TMP'; |
||
6132 | } |
||
6133 | |||
6134 | // Check if user is already subscribe to course |
||
6135 | $userSubscription = $cuRepo->findBy([ |
||
6136 | 'course' => $course, |
||
6137 | 'user' => $userId, |
||
6138 | ]); |
||
6139 | |||
6140 | if (!empty($userSubscription)) { |
||
6141 | return 'YES'; |
||
6142 | } |
||
6143 | |||
6144 | return 'NO'; |
||
6145 | } |
||
6146 | } |
||
6147 |
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.
Unreachable code is most often the result of
return
,die
orexit
statements that have been added for debug purposes.In the above example, the last
return false
will never be executed, because a return statement has already been met in every possible execution path.