| @@ -46,8 +46,12 @@ | ||
| 46 | 46 | * @return float Product Price. |
| 47 | 47 | * @throws \Exception If setting is not found. |
| 48 | 48 | */ |
| 49 | 49 | public function get_product_discounted_price( $price, $product ) {//phpcs:ignore |
| 50 | + if ( Settings::get( 'discount_priority_type' ) === 'woocommerce_coupon' ) { | |
| 51 | + return $price; // Return original price if WooCommerce coupon is used. | |
| 52 | + } | |
| 53 | + | |
| 50 | 54 | if ( $product instanceof \WC_Product ) { |
| 51 | 55 | // Init product base intents and exclude cart-based intents. |
| 52 | 56 | $this->intents = $this->prepare_intents( array( 'Product' ) ); |
| 53 | 57 | |
| @@ -64,8 +68,10 @@ | ||
| 64 | 68 | } |
| 65 | 69 | |
| 66 | 70 | $discounts = array(); |
| 67 | 71 | |
| 72 | + $prev_discount = PHP_INT_MAX; | |
| 73 | + | |
| 68 | 74 | // Foreach intent, apply the discount. |
| 69 | 75 | foreach ( $this->intents as $intent ) { |
| 70 | 76 | /** |
| 71 | 77 | * Get a discount limit form campaign. |
| @@ -90,10 +96,15 @@ | ||
| 90 | 96 | if ( empty( $discount ) ) { |
| 91 | 97 | continue; |
| 92 | 98 | } |
| 93 | 99 | |
| 94 | - // Store discount keyed by campaign id so the winning amount maps back to the right campaign. | |
| 95 | - $discounts[ $intent->campaign->id ] = $discount; | |
| 100 | + // Get applied discount campaign. | |
| 101 | + if ( $discount > 0 && $prev_discount > $discount ) { | |
| 102 | + $this->applied_campaign_id = $intent->campaign->id; | |
| 103 | + $prev_discount = $discount; | |
| 104 | + } | |
| 105 | + | |
| 106 | + $discounts[] = $discount; | |
| 96 | 107 | } |
| 97 | 108 | |
| 98 | 109 | // If no discount is applied, return the original price. |
| 99 | 110 | if ( empty( $discounts ) ) { |
| @@ -101,17 +112,13 @@ | ||
| 101 | 112 | } |
| 102 | 113 | |
| 103 | 114 | $discount_type = $intent->campaign->discount_rules[0]['discount_type']; |
| 104 | 115 | |
| 105 | - // Pick the winning discount amount, then map it back to the campaign that produced it. | |
| 106 | - $base_discount = $this->min_max_average( array_values( $discounts ) ); | |
| 107 | - $this->applied_campaign_id = (int) array_search( $base_discount, $discounts, true ); | |
| 108 | - | |
| 109 | 116 | /** |
| 110 | 117 | * Get the min or max discount amount according to plugin settings. |
| 111 | 118 | * Apply the filter to modify final discounted amount based on discount types. |
| 112 | 119 | */ |
| 113 | - $discounted_amount = apply_filters( 'disco_final_discounted_amount', $base_discount, $discount_type ); | |
| 120 | + $discounted_amount = apply_filters( 'disco_final_discounted_amount', $this->min_max_average( $discounts ), $discount_type ); | |
| 114 | 121 | |
| 115 | 122 | if ( $discounted_amount <= $price ) { |
| 116 | 123 | // Get an applied campaign from DiscountLimit class. |
| 117 | 124 | ( new UserLimit )->disco_start_session_on_checkout( $this->applied_campaign_id ); |
| @@ -136,8 +143,12 @@ | ||
| 136 | 143 | if ( $cart->is_empty() ) { |
| 137 | 144 | return $cart; |
| 138 | 145 | } |
| 139 | 146 | |
| 147 | + if ( Settings::get( 'discount_priority_type' ) === 'woocommerce_coupon' ) { | |
| 148 | + return $cart; | |
| 149 | + } | |
| 150 | + | |
| 140 | 151 | // Init Cart - Based Intents except Product & Shipping Intent. |
| 141 | 152 | $this->intents = $this->prepare_intents( array( 'Cart' ) ); |
| 142 | 153 | |
| 143 | 154 | if ( ! empty( $this->intents ) && $cart->get_cart_contents_count() > 0 ) { |
| @@ -200,10 +211,8 @@ | ||
| 200 | 211 | if ( ! empty( $discount_label ) ) { |
| 201 | 212 | $label = $discount_label; |
| 202 | 213 | } |
| 203 | 214 | |
| 204 | - $cart_fee = $this->get_discount_exclude_tax( $cart_fee, $cart ); | |
| 205 | - | |
| 206 | 215 | $cart->add_fee( $label, -$cart_fee ); |
| 207 | 216 | $cart->set_session(); |
| 208 | 217 | } |
| 209 | 218 | } |
| @@ -226,8 +235,12 @@ | ||
| 226 | 235 | if ( ! defined( 'DOING_AJAX' ) && is_admin() ) { |
| 227 | 236 | return $cart; |
| 228 | 237 | } |
| 229 | 238 | |
| 239 | + if ( Settings::get( 'discount_priority_type' ) === 'woocommerce_coupon' ) { | |
| 240 | + return $cart; | |
| 241 | + } | |
| 242 | + | |
| 230 | 243 | // Init Cart - Based Intents except Product & Shipping Intent. |
| 231 | 244 | $this->intents = $this->prepare_intents( array( 'Bulk', 'Bundle', 'BOGO' ) ); |
| 232 | 245 | |
| 233 | 246 | $discounts = $this->prepare_item_discounts( $this->intents, $cart ); |
| @@ -256,10 +269,8 @@ | ||
| 256 | 269 | $total_discount += $discounts[ $id ]; |
| 257 | 270 | } |
| 258 | 271 | |
| 259 | 272 | if ( $total_discount > 0 ) { |
| 260 | - $total_discount = $this->get_discount_exclude_tax( $total_discount, $cart ); | |
| 261 | - | |
| 262 | 273 | $cart->add_fee( __( 'Discount', 'disco' ), -$total_discount ); |
| 263 | 274 | } |
| 264 | 275 | |
| 265 | 276 | $cart->set_session(); |
| @@ -283,8 +294,12 @@ | ||
| 283 | 294 | if ( ! defined( 'DOING_AJAX' ) && is_admin() ) { |
| 284 | 295 | return $cart; |
| 285 | 296 | } |
| 286 | 297 | |
| 298 | + if ( Settings::get( 'discount_priority_type' ) === 'woocommerce_coupon' ) { | |
| 299 | + return $cart; | |
| 300 | + } | |
| 301 | + | |
| 287 | 302 | // Init Cart - Based Intents except Product & Shipping Intent. |
| 288 | 303 | $this->intents = $this->prepare_intents( array( 'BOGO' ) ); |
| 289 | 304 | |
| 290 | 305 | return $this->prepare_item_discounts_bogo_free( $this->intents, $cart ); |
| @@ -295,62 +310,55 @@ | ||
| 295 | 310 | * |
| 296 | 311 | * @return bool |
| 297 | 312 | */ |
| 298 | 313 | public function apply_free_shipping() { //phpcs:ignore |
| 299 | - return ! empty( $this->get_applied_free_shipping_campaign_ids() ); | |
| 300 | - } | |
| 301 | - | |
| 302 | - /** | |
| 303 | - * Evaluate the Shipping intents and return the IDs of every campaign that | |
| 304 | - * currently grants free shipping (respecting per-user usage limits). | |
| 305 | - * | |
| 306 | - * This is the single source of truth for "which free-shipping campaigns | |
| 307 | - * apply right now". It is used both to decide whether to add a free shipping | |
| 308 | - * rate and to persist the campaign IDs to the order meta at checkout. It does | |
| 309 | - * NOT rely on the WC session or cached shipping rates, so it is safe to call | |
| 310 | - * during order creation. | |
| 311 | - * | |
| 312 | - * @return array<int> Applied free-shipping campaign IDs. | |
| 313 | - */ | |
| 314 | - public function get_applied_free_shipping_campaign_ids() { | |
| 315 | 314 | if ( ! $this->cart_is_valid() ) { |
| 316 | - return array(); | |
| 315 | + return false; | |
| 317 | 316 | } |
| 318 | 317 | |
| 319 | - $cart = WC()->cart; | |
| 320 | - $this->intents = $this->prepare_intents( array( 'Shipping' ) ); | |
| 321 | - $campaign_ids = array(); | |
| 318 | + $cart = WC()->cart; | |
| 322 | 319 | |
| 323 | - if ( empty( $this->intents ) ) { | |
| 324 | - return $campaign_ids; | |
| 320 | + if ( Settings::get( 'discount_priority_type' ) === 'woocommerce_coupon' ) { | |
| 321 | + return false; // Return false if WooCommerce coupon is used. | |
| 325 | 322 | } |
| 326 | 323 | |
| 327 | - foreach ( $this->intents as $intent ) { | |
| 328 | - /** | |
| 329 | - * Get a discount limit from campaign. | |
| 330 | - * | |
| 331 | - * Compare with total applied count and skip if the user limit is hit. | |
| 332 | - */ | |
| 333 | - $discount_limit = $intent->campaign->discount_max_user; | |
| 324 | + $this->intents = $this->prepare_intents( array( 'Shipping' ) ); | |
| 325 | + $shippings = array(); | |
| 334 | 326 | |
| 335 | - if ( ! empty( $discount_limit ) ) { | |
| 327 | + if ( ! empty( $this->intents ) ) { | |
| 328 | + foreach ( $this->intents as $intent ) { | |
| 329 | + /** | |
| 330 | + * Get a discount limit form campaign. | |
| 331 | + * | |
| 332 | + * Compare with total product meta and apply discount | |
| 333 | + */ | |
| 334 | + $discount_limit = $intent->campaign->discount_max_user; | |
| 335 | + $applied_campaign_id = $intent->campaign->id; | |
| 336 | 336 | $total_applied_campaign = ( new UserLimit )->disco_get_total_applied_campaign( $intent->campaign->id ); |
| 337 | 337 | |
| 338 | - if ( $total_applied_campaign >= $discount_limit ) { | |
| 338 | + if ( | |
| 339 | + ! empty( $discount_limit ) | |
| 340 | + && ( | |
| 341 | + $discount_limit >= 0 | |
| 342 | + && $total_applied_campaign >= $discount_limit | |
| 343 | + ) | |
| 344 | + ) { | |
| 339 | 345 | continue; |
| 340 | 346 | } |
| 341 | - } | |
| 342 | 347 | |
| 343 | - $items = $this->get_items_for_discount( $cart, $intent->campaign ); | |
| 348 | + $items = $this->get_items_for_discount( $cart, $intent->campaign ); | |
| 349 | + $shippings[] = $intent->get_discounts( $items, $cart ); | |
| 344 | 350 | |
| 345 | - if ( 'free_shipping' !== $intent->get_discounts( $items, $cart ) ) { | |
| 346 | - continue; | |
| 351 | + if ( !in_array( 'free_shipping', $shippings, true ) ) { | |
| 352 | + continue; | |
| 353 | + } | |
| 354 | + | |
| 355 | + // Get an applied campaign from DiscountLimit class. | |
| 356 | + ( new UserLimit )->disco_start_session_on_checkout( $applied_campaign_id ); | |
| 347 | 357 | } |
| 348 | - | |
| 349 | - $campaign_ids[] = (int) $intent->campaign->id; | |
| 350 | 358 | } |
| 351 | 359 | |
| 352 | - return $campaign_ids; | |
| 360 | + return in_array( 'free_shipping', $shippings, true ); | |
| 353 | 361 | } |
| 354 | 362 | |
| 355 | 363 | /** |
| 356 | 364 | * Get offers for a product. |