PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.20
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.20
1.4.21 1.4.20 1.4.19 1.4.18 1.4.17 1.4.16 1.4.15 1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 All 184 releases
← All changes | app/Intents/IntentHelper.php +58 -7 1.4.16 → 1.4.20 View file →
@@ -251,17 +251,39 @@
251 251 public function calculate_discount( $cost, $discount_type, $discount_value ) {
252 252 $cost = (float) $cost;
253 253 $discount_value = (float) $discount_value;
254 254
255 - if ( 'percent' === $discount_type ) {
256 - $cost = $cost * $discount_value / 100;
257 - }
255 + switch ( $discount_type ) {
256 + case 'percent':
257 + return $cost * $discount_value / 100;
258 258
259 - if ( 'fixed' === $discount_type || 'fixed_per_product' === $discount_type ) {
260 - $cost = $discount_value;
261 - }
259 + case 'fixed':
260 + case 'fixed_per_product':
261 + return $discount_value;
262 262
263 - return $cost;
263 + case 'free':
264 + // The whole cost comes off, which is what makes the item free.
265 + return $cost;
266 +
267 + default:
268 + /**
269 + * Anything else discounts nothing.
270 + *
271 + * This used to fall through and return $cost untouched, which the
272 + * callers then treat as the discount: ProductIntent hands it the
273 + * product price and CartIntent the cart subtotal, so an
274 + * unrecognised type gave away the product or the entire cart.
275 + *
276 + * Only Bulk, Bundle and BOGO route through the Calc classes,
277 + * where every type has an implementation; Product and Cart come
278 + * straight here, so the gap was reachable by any rule carrying a
279 + * type this method does not know: a campaign saved while
280 + * fixed_price and percent_per_product were still offered in the
281 + * builder, a REST write (discount_type inside discount_rules is
282 + * not validated), or a hand edited row.
283 + */
284 + return 0.0;
285 + }//end switch
264 286 }
265 287
266 288 /**
267 289 * Get the discounted price.
@@ -492,8 +514,37 @@
492 514 $total_qualifying_units += $eligible_line['eligible_qty'];
493 515 }
494 516
495 517 $discountable_units = $this->grouped_discount_budget( $rule, $total_qualifying_units );
518 +
519 + /**
520 + * A flat amount is charged for the pooled group as a whole.
521 + *
522 + * Pooling exists so the cart together can reach the tier minimum, so
523 + * the rule qualifies for the group rather than for each line that
524 + * contributed quantity. The Calc layer returns the rule value whole
525 + * for every line it is handed, because a flat amount does not scale
526 + * with units, so spreading it across lines multiplied the discount by
527 + * the line count: a flat 10 came out as 20 over two lines.
528 + *
529 + * It is applied to the first eligible line carrying the entire pooled
530 + * budget, which is what lets a recursive rule still charge once per
531 + * bundle: the Calc layer derives the bundle count from that quantity.
532 + * Per unit types keep every line, since their amount is meant to
533 + * scale with the units.
534 + */
535 + if ( in_array( $rule['discount_type'], array( 'fixed', 'fixed_price' ), true ) ) {
536 + $first_line = reset( $eligible_lines );
537 +
538 + if ( ! empty( $first_line['item'] ) && $discountable_units > 0 ) {
539 + $item = $first_line['item'];
540 + $item['disco_forced_qty'] = $discountable_units;
541 +
542 + $this->apply_rule_to_discount( $discounts, $campaign, $rule, $item, $cart, $total_applicable_qty );
543 + }
544 +
545 + continue;
546 + }
496 547
497 548 // Hand out the discountable units across the eligible lines in cart order.
498 549 foreach ( $eligible_lines as $eligible_line ) {
499 550 if ( $discountable_units <= 0 ) {