· 5 years ago · Mar 17, 2020, 11:14 PM
1<?php
2
3
4 class ot_discount {
5 var $title, $output;
6 var $delete_tables = false;
7
8 function __construct() {
9 $this->code = 'ot_discount';
10 $this->version = '4.4.2 BS';
11 $this->title = MODULE_ORDER_TOTAL_DISCOUNT_TITLE;
12 $this->description = MODULE_ORDER_TOTAL_DISCOUNT_DESCRIPTION;
13 $this->enabled = ((defined('MODULE_ORDER_TOTAL_DISCOUNT_STATUS') && MODULE_ORDER_TOTAL_DISCOUNT_STATUS == 'true') ? true : false);
14 $this->sort_order = defined('MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER')? MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER:0;
15 $this->delete_tables = defined('MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER')?(MODULE_ORDER_TOTAL_DISCOUNT_DELETE_TABLES == 'True'):false;
16
17 $this->output = array();
18 }
19
20 function process() {
21 global $order, $currencies, $currency, $customer_id, $discount, $sess_discount_code;
22
23 $discount = 0;
24 $subtotal_correction = 0;
25 $tax_correction = 0;
26 $shipping_discount = 'false';
27
28 if (!empty($sess_discount_code)) {
29 $check_query = tep_db_query("select count(*) as total, dc.number_of_use from discount_codes dc, customers_to_discount_codes c2dc where dc.discount_codes_id = c2dc.discount_codes_id and dc.discount_codes = '" . tep_db_input($sess_discount_code) . "' and c2dc.customers_id = '" . (int)$customer_id . "' group by c2dc.customers_id limit 1");
30 if (tep_db_num_rows($check_query) == 0) {
31 $check['number_of_use'] = 0;
32 } else {
33 $check = tep_db_fetch_array($check_query);
34 }
35 if (($check['number_of_use'] == 0 ? 1 : ($check['total'] < $check['number_of_use'] ? 1 : 0)) == 1) {
36 $check_query = tep_db_query("select * from discount_codes where discount_codes = '" . tep_db_input($sess_discount_code) . "' and if(expires_date = '0000-00-00', date_format(date_add(now(), interval 1 day), '%Y-%m-%d'), expires_date) >= date_format(now(), '%Y-%m-%d') and minimum_order_amount <= " . $order->info['subtotal'] . " and status = '1' limit 1");
37 if (tep_db_num_rows($check_query)) {
38 $check = tep_db_fetch_array($check_query);
39 $order_info = $check['order_info'];
40
41 if (!empty($check['customers_id'])) {
42 $customers = explode(',', $check['customers_id']);
43 } else {
44 $customers = array($customer_id);
45 }
46
47 if (!empty($check['newsletter'])) {
48 $check_query_news = tep_db_query("select customers_newsletter from customers where customers_id = '" . (int)$customer_id . "'");
49 $check_news = tep_db_fetch_array($check_query_news);
50 $newsletter = $check_news['customers_newsletter'];
51 }
52
53 if (!empty($check['order_number'])) {
54 $check_query_order = tep_db_query("select count(*) as orders from orders where customers_id = '" . (int)$customer_id . "'");
55 $check_order = tep_db_fetch_array($check_query_order);
56 $orders = $check_order['orders']+1;
57 // Support for PWA guest orders BEGIN
58 if (tep_db_num_rows(tep_db_query("select * from information_schema.columns where table_schema='". DB_DATABASE . "' and table_name='orders' and column_name like 'customers_guest'")) == 1 ) {
59 $check_query_mail = tep_db_query("select customers_email_address from customers where customers_id = '" . (int)$customer_id . "'");
60 $check_mail = tep_db_fetch_array($check_query_mail);
61 if (!empty($check_mail['customers_email_address'])) {
62 $check_query_order_guest = tep_db_query("select count(*) as orders from orders where customers_email_address = '" . $check_mail['customers_email_address'] . "' and customers_guest = '1'");
63 $check_order_guest = tep_db_fetch_array($check_query_order_guest);
64 $orders = $orders + $check_order_guest['orders'];
65 }
66 }
67 // Support for PWA guest orders END
68 }
69
70 if ( (empty($check['newsletter']) || $newsletter == 1) && (empty($check['order_number']) || $orders == $check['order_number']) ) {
71 if (in_array($customer_id, $customers)) {
72 if (!empty($check['products_id']) || !empty($check['categories_id']) || !empty($check['manufacturers_id']) || (int)$check['exclude_specials'] == 1) {
73
74 $products = array();
75 if (!empty($check['products_id'])) {
76 $products = explode(',', $check['products_id']);
77 } elseif (!empty($check['categories_id'])) {
78 $product_query = tep_db_query("select products_id from products_to_categories where categories_id in (" . $check['categories_id'] . ")" . (empty($check['excluded_products_id']) ? '' : " and products_id not in (" . $check['excluded_products_id'] . ")"));
79 while ($product = tep_db_fetch_array($product_query)) {
80 $products[] = $product['products_id'];
81 }
82 } elseif (!empty($check['manufacturers_id'])) {
83 $product_query = tep_db_query("select products_id from products where manufacturers_id in (" . $check['manufacturers_id'] . ")" . (empty($check['excluded_products_id']) ? '' : " and products_id not in (" . $check['excluded_products_id'] . ")"));
84 while ($product = tep_db_fetch_array($product_query)) {
85 $products[] = $product['products_id'];
86 }
87 } elseif ((int)$check['exclude_specials'] == 1) {
88 for ($i = 0, $n = sizeof($order->products); $i < $n; $i++) {
89 $products[] = $order->products[$i]['id'];
90 }
91 }
92
93 if ((int)$check['exclude_specials'] == 1) {
94 $specials = array();
95 $product_query = tep_db_query("select p.products_id from products p, specials s where p.products_id = s.products_id and s.status = '1' and ifnull(s.expires_date, now()) >= now()");
96 while ($product = tep_db_fetch_array($product_query)) {
97 $specials[] = $product['products_id'];
98 }
99 if (sizeof($specials) > 0) {
100 $products = array_diff($products, $specials);
101 }
102 }
103
104 if (empty($check['number_of_products'])) {
105 $k = PHP_INT_MAX;
106 } else {
107 $k = $check['number_of_products'];
108 }
109
110 for ($i = 0, $n = sizeof($order->products); $i < $n; $i++) {
111 if (in_array(tep_get_prid($order->products[$i]['id']), $products)) {
112 if ($k >= $order->products[$i]['qty']) {
113 $products_discount = $this->format_raw(strpos($check['discount_values'], '%') === false ? $check['discount_values'] * $order->products[$i]['qty'] : tep_add_tax($order->products[$i]['final_price'], $order->products[$i]['tax']) * str_replace('%', '', $check['discount_values']) / 100 * $order->products[$i]['qty']);
114 $k -= $order->products[$i]['qty'];
115 } else {
116 $products_discount = $this->format_raw(strpos($check['discount_values'], '%') === false ? $check['discount_values'] * $k : tep_add_tax($order->products[$i]['final_price'], $order->products[$i]['tax']) * str_replace('%', '', $check['discount_values']) / 100 * $k);
117 $k = 0;
118 }
119
120 if (!empty($order->products[$i]['tax'])) {
121 if (DISPLAY_PRICE_WITH_TAX != 'true') {
122 $tax_correction = $currencies->format_raw(($products_discount * ($order->products[$i]['tax'] / 100)));
123 $order->info['total'] -= $tax_correction;
124 } else {
125 $tax_correction = $currencies->format_raw($products_discount - $products_discount / (1.0 + $order->products[$i]['tax'] / 100));
126 }
127 }
128 $subtotal_correction += $order->products[$i]['final_price']; //use for tax calculation only products which have taxes
129 $order->info['tax'] -= $tax_correction;
130 $order->info['tax_groups'][$order->products[$i]['tax_description']] -= $tax_correction;
131 $discount += $products_discount;
132 }
133 }
134
135 // revert currency conversion to default currency
136 $order->info['total'] -= $currencies->format_raw($discount, true, $order->info['currency'], 1/$order->info['currency_value']);
137
138 // format discount for output, do not apply currency conversion, product price already converted to order currency
139 $discount_formatted = $currencies->format($discount, false);
140
141 } elseif (!empty($check['orders_total'])) {
142 if ($check['orders_total'] == 2) {
143 $discount = (strpos($check['discount_values'], '%') === false ? $check['discount_values'] : $order->info['subtotal'] * str_replace('%', '', $check['discount_values']) / 100);
144 if ($discount > $order->info['subtotal']) {
145 $discount = $order->info['subtotal'];
146 }
147 $ot_taxrates = 0;
148 if (DISPLAY_PRICE_WITH_TAX == 'true' && MODULE_ORDER_TOTAL_DISCOUNT_TAX_CALCULATION_EXCL == 'true' ) {
149 // find order subtotal excl. tax
150 $order_subtotal_excl = null;
151 for ($i = 0, $n = sizeof($order->products); $i < $n; $i++) {
152 $order_subtotal_excl += $order->products[$i]['qty'] * $order->products[$i]['final_price'];
153 }
154 for ($i = 0, $n = sizeof($order->products); $i < $n; $i++) {
155 if (!empty($order->products[$i]['tax'])) {
156 $portion = ($order->products[$i]['qty'] * $order->products[$i]['final_price']) / $order_subtotal_excl;
157 $global_tax_correction = $discount * $portion;
158 $discount_excl = ($global_tax_correction / (1+$order->products[$i]['tax']/100));
159 $discount_tax = $global_tax_correction - $discount_excl;
160 // strip discount from order total
161 $order->info['total'] -= $currencies->format_raw($global_tax_correction);
162 // correct tax
163 if (!empty($discount_tax) && is_array($order->info['tax_groups']) && count($order->info['tax_groups']) > 0) {
164 foreach ($order->info['tax_groups'] as $key => $value) {
165 if ($key == $order->products[$i]['tax_description']) {
166 $order->info['tax_groups'][$key] -= $discount_tax;
167 $order->info['tax'] -= $discount_tax;
168 }
169 } // end for each tax group
170 } // if discount tax and tax groups
171 } // end if products tax
172 } // end products loop
173 } else {
174 for ($i = 0, $n = sizeof($order->products); $i < $n; $i++) {
175 if (!empty($order->products[$i]['tax'])) {
176 //here it gets complicate, we have to find the proportional part of the global discount for each product
177 $global_tax_correction = $this->format_raw($order->products[$i]['qty']*(( $order->products[$i]['final_price']/$order->info['subtotal'])*$discount)+(($order->products[$i]['qty']* $order->products[$i]['final_price']/$order->info['subtotal'])*$discount) * ($order->products[$i]['tax'] / 100));
178 $order->info['total'] -= $global_tax_correction;
179 }
180 }
181
182 if (is_array($order->info['tax_groups']) && count($order->info['tax_groups']) > 0) {
183 foreach ($order->info['tax_groups'] as $key => $value) {
184 if (!empty($value)) {
185 $order->info['tax_groups'][$key] = $this->format_raw(($order->info['subtotal'] - $discount) * ($value / $order->info['subtotal']));
186 $ot_taxrates += $order->info['tax_groups'][$key];
187 }
188 }
189 }
190 }
191 if (!empty($ot_taxrates)) {
192 $order->info['tax'] = $ot_taxrates;
193 } else {
194 $order->info['total'] -= $discount;
195 }
196 }
197 // format discount for output, apply currency conversion
198 $discount_formatted = $currencies->format($discount, true, $order->info['currency'], $order->info['currency_value']);
199
200 } elseif (!empty($check['shipping'])) { //.eof $check['orders_total']
201 $shipping_tax = 0;
202 if ($check['shipping'] == 2) {
203 $module = substr($GLOBALS['shipping']['id'], 0, strpos($GLOBALS['shipping']['id'], '_'));
204 if (tep_not_null($order->info['shipping_method'])) {
205 if ($GLOBALS[$module]->tax_class > 0) {
206 $shipping_tax = tep_get_tax_rate($GLOBALS[$module]->tax_class, $order->delivery['country']['id'], $order->delivery['zone_id']);
207 }
208 }
209 $discount = $order->info['shipping_cost'] * str_replace('%', '', strtolower($check['discount_values'])) / 100;
210 if ($discount > $order->info['shipping_cost']) {
211 $discount = $order->info['shipping_cost'];
212 }
213 if (DISPLAY_PRICE_WITH_TAX == 'true' && MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER <= MODULE_ORDER_TOTAL_SHIPPING_SORT_ORDER ) $discount += tep_calculate_tax($discount, $shipping_tax);
214 $ot_taxrates = 0;
215 if (is_array($order->info['tax_groups']) && count($order->info['tax_groups']) > 0) {
216 if ( MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER <= MODULE_ORDER_TOTAL_SHIPPING_SORT_ORDER ) { // discount before shipping
217 foreach ($order->info['tax_groups'] as $key => $value) {
218 if (!empty($value)) {
219 if ($shipping_tax > 0) {
220 $order->info['tax_groups'][$key] = $currencies->format_raw(($order->info['subtotal'] - $discount) * ($value / $order->info['subtotal']));
221 } else {
222 $order->info['tax_groups'][$key] = $currencies->format_raw(($order->info['subtotal']) * ($value / $order->info['subtotal']));
223 }
224 $ot_taxrates += $order->info['tax_groups'][$key];
225 }
226 }
227 } else { // shipping before discount
228 foreach ($order->info['tax_groups'] as $key => $value) {
229 if (!empty($value)) {
230 if ($shipping_tax > 0) {
231 $order->info['tax_groups'][$key] = $currencies->format_raw(($order->info['subtotal']) * (($value - tep_calculate_tax(((DISPLAY_PRICE_WITH_TAX == 'true')? $discount / (1 + $shipping_tax / 100) : $discount ), $shipping_tax)) / $order->info['subtotal']));
232 } else {
233 $order->info['tax_groups'][$key] = $currencies->format_raw(($order->info['subtotal']) * ($value / $order->info['subtotal']));
234 }
235 $ot_taxrates += $order->info['tax_groups'][$key];
236 }
237 }
238 }
239 }
240 $order->info['total'] -= $discount;
241 if (DISPLAY_PRICE_WITH_TAX != 'true') $order->info['total'] -= tep_calculate_tax($order->info['shipping_cost'], $shipping_tax);
242 if (!empty($ot_taxrates)) $order->info['tax'] = $ot_taxrates;
243 $shipping_discount = 'true';
244 }
245
246 // format discount for output, apply currency conversion
247 $discount_formatted = $currencies->format($discount, true, $order->info['currency'], $order->info['currency_value']);
248
249 } //.eof $check['shipping']
250 if ( MODULE_ORDER_TOTAL_DISCOUNT_SHOW_SHIPPING_DISCOUNTED == 'true' && $shipping_discount == 'true') {
251 $order->info['shipping_cost'] -= $discount;
252 }
253
254 if ( MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER <= MODULE_ORDER_TOTAL_SUBTOTAL_SORT_ORDER ) { // discount before order subtotal
255 $order->info['subtotal'] -= $discount;
256 }
257 } // eof check newsletter and order number
258 }
259 }
260 }
261 }
262
263 if (!empty($discount)) {
264 $this->output[] = array('title' => (($shipping_discount == 'true')? TEXT_SHIPPING_DISCOUNT : TEXT_DISCOUNT) . (strpos($check['discount_values'], '%') ? ' ' . $check['discount_values'] . ' ' : '') . (!empty($order_info) ? ' (' . $sess_discount_code . ')' : '') . ':',
265 'text' => '<font color="#ff0000">-' . $discount_formatted . '</font>',
266 'value' => -$discount);
267 }
268 }
269
270 function check() {
271 if (!isset($this->_check)) {
272 $check_query = tep_db_query("select configuration_value from configuration where configuration_key = 'MODULE_ORDER_TOTAL_DISCOUNT_STATUS'");
273 $this->_check = tep_db_num_rows($check_query);
274 }
275
276 return $this->_check;
277 }
278
279 function keys() {
280 return array('MODULE_ORDER_TOTAL_DISCOUNT_VERSION', 'MODULE_ORDER_TOTAL_DISCOUNT_STATUS', 'MODULE_ORDER_TOTAL_DISCOUNT_SHOW_SHIPPING_DISCOUNTED', 'MODULE_ORDER_TOTAL_DISCOUNT_TAX_CALCULATION_EXCL', 'MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER', 'MODULE_ORDER_TOTAL_DISCOUNT_DELETE_TABLES');
281 }
282
283 function install() {
284 tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ( 'Module Version', 'MODULE_ORDER_TOTAL_DISCOUNT_VERSION', '" . $this->version . "', 'The version of this module that you are running', '6', '0', 'tep_version_readonly(', now())");
285 tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Display Discount', 'MODULE_ORDER_TOTAL_DISCOUNT_STATUS', 'true', 'Do you want to display the discount value?', '6', '1','tep_cfg_select_option(array(\'true\', \'false\'), ', now())");
286 tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Show shipping fee discounted', 'MODULE_ORDER_TOTAL_DISCOUNT_SHOW_SHIPPING_DISCOUNTED', 'false', 'Do you want to show the shipping cost with applied discount?<br>Only applies if ot discount module is shown before ot shipping module.', '6', '1','tep_cfg_select_option(array(\'true\', \'false\'), ', now())");
287 tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Base discount tax on prices excl.', 'MODULE_ORDER_TOTAL_DISCOUNT_TAX_CALCULATION_EXCL', 'true', 'Shall discount tax be calculated by portions based on product prices excl tax?<br> Only affects stores showing prices incl. tax and mixed orders including products with different tax rates.', '6', '1','tep_cfg_select_option(array(\'true\', \'false\'), ', now())");
288 tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort Order', 'MODULE_ORDER_TOTAL_DISCOUNT_SORT_ORDER', '2', 'Sort order of display.', '6', '2', now())");
289 tep_db_query("insert into configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Delete auto created tables when uninstalling', 'MODULE_ORDER_TOTAL_DISCOUNT_DELETE_TABLES', 'False', 'Do you want to remove the tables that were created during installing this module?<br><i>Note: all the created discount codes will be deleted</i>.', '6', '13', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
290 // CREATE NEEDED TABLES INTO DB
291 tep_db_query("
292 CREATE TABLE IF NOT EXISTS `customers_to_discount_codes` (
293 `customers_id` int(11) NOT NULL default '0',
294 `discount_codes_id` int(11) NOT NULL default '0',
295 KEY `customers_id` (`customers_id`),
296 KEY `discount_codes_id` (`discount_codes_id`)
297 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
298 ");
299 tep_db_query("
300 CREATE TABLE IF NOT EXISTS `discount_codes` (
301 `discount_codes_id` int(11) NOT NULL auto_increment,
302 `products_id` text,
303 `categories_id` text,
304 `manufacturers_id` text,
305 `excluded_products_id` text,
306 `customers_id` text,
307 `orders_total` tinyint(1) NOT NULL default '0',
308 `shipping` tinyint(1) NOT NULL default '0',
309 `order_info` tinyint(1) NOT NULL default '0',
310 `exclude_specials` tinyint(1) NOT NULL default '0',
311 `discount_codes` varchar(8) NOT NULL default '',
312 `discount_values` varchar(8) NOT NULL default '',
313 `minimum_order_amount` decimal(15,4) NOT NULL default '0.0000',
314 `expires_date` date NOT NULL default '0000-00-00',
315 `number_of_orders` int(4) NOT NULL default '0',
316 `number_of_use` int(4) NOT NULL default '0',
317 `number_of_products` int(4) NOT NULL default '0',
318 `status` tinyint(1) NOT NULL default '1',
319 PRIMARY KEY (`discount_codes_id`)
320 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
321 ");
322 // check if new field exist if not create
323 $check = tep_db_query("SHOW COLUMNS FROM `discount_codes` LIKE 'shipping'");
324 $exists = (tep_db_num_rows($check))?TRUE:FALSE;
325 if(!$exists) {
326 tep_db_query("ALTER TABLE `discount_codes` ADD `shipping` tinyint(1) NOT NULL default '0'");
327 }
328 $check = tep_db_query("SHOW COLUMNS FROM `discount_codes` LIKE 'newsletter'");
329 $exists = (tep_db_num_rows($check))?TRUE:FALSE;
330 if(!$exists) {
331 tep_db_query("ALTER TABLE `discount_codes` ADD `newsletter` tinyint(1) NOT NULL default '0'");
332 }
333 $check = tep_db_query("SHOW COLUMNS FROM `discount_codes` LIKE 'order_number'");
334 $exists = (tep_db_num_rows($check))?TRUE:FALSE;
335 if(!$exists) {
336 tep_db_query("ALTER TABLE `discount_codes` ADD `order_number` tinyint(1) NOT NULL default '0'");
337 }
338 if (defined('OSCOM_APP_PAYPAL_PS_STATUS') && in_array(OSCOM_APP_PAYPAL_PS_STATUS, array('1', '0'))) {
339 $check = tep_db_query("SHOW COLUMNS FROM `orders` LIKE 'discount_codes'");
340 $exists = (tep_db_num_rows($check))?TRUE:FALSE;
341 if(!$exists) {
342 tep_db_query("ALTER TABLE `orders` ADD `discount_codes` varchar(8) NOT NULL default ''");
343 }
344 }
345 }
346
347 function remove() {
348 tep_db_query("delete from configuration where configuration_key in ('" . implode("', '", $this->keys()) . "')");
349 // DROP TABLE IF SET TO TRUE
350 if($this->delete_tables){
351 tep_db_query("DROP TABLE IF EXISTS `customers_to_discount_codes`");
352 tep_db_query("DROP TABLE IF EXISTS `discount_codes`");
353 }
354 }
355
356 function format_raw($number, $currency_code = '', $currency_value = '') {
357 global $currencies, $currency;
358
359 if (empty($currency_code) || !$currencies->is_set($currency_code)) {
360 $currency_code = $currency;
361 }
362
363 if (empty($currency_value) || !is_numeric($currency_value)) {
364 $currency_value = $currencies->currencies[$currency_code]['value'];
365 }
366
367 return number_format(tep_round($number * $currency_value, $currencies->currencies[$currency_code]['decimal_places']), $currencies->currencies[$currency_code]['decimal_places'], '.', '');
368 }
369 }
370
371 ////
372 // Function for version read out
373 if(!function_exists('tep_version_readonly')) {
374 function tep_version_readonly($value){
375 $version_text = $value;
376 return $version_text;
377 }
378 }
379
380?>