PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.16
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.16
1.4.24 1.4.23 1.4.22 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 All 187 releases
← All changes | app/Calc/CalcFixed.php +32 -10 1.4.4 → 1.4.16 View file →
@@ -77,25 +77,43 @@
77 77 public function calculate_discount(): float { // phpcs:ignore
78 78 $discount_amount = 0;
79 79 $fixed_discount = $this->rule['discount_value'];
80 80 $quantity = (int) $this->item['quantity'];
81 +
82 + /**
83 + * "Count Quantity As" combined / variations: a fixed amount is a flat
84 + * line discount, so eligibility (any eligible unit) gates it once rather
85 + * than scaling with the eligible unit count.
86 + */
87 + if ( isset( $this->item['disco_forced_qty'] ) ) {
88 + $forced = max( 0, (int) $this->item['disco_forced_qty'] );
89 + $this->discounted_quantities = $forced;
90 +
91 + return apply_filters( 'disco_final_discounted_amount', $forced > 0 ? (float) $fixed_discount : 0, 'fixed' );
92 + }
93 +
81 94 $min = $this->rule['min'] ? (int) $this->rule['min'] : 0; // phpcs:ignore
82 95 $max = $this->rule['max'] ? (int) $this->rule['max'] : 0; // phpcs:ignore
83 96 $recursive = isset( $this->rule['recursive'] ) && 'yes' === $this->rule['recursive']; // phpcs:ignore
84 - $item_id = $this->item['product_id'];
85 - $rule_ids = array_column( $this->rule['get_ids'], 'id' );
97 + $item_id = $this->item['product_id'];
98 + $rule_ids = array_column( $this->rule['get_ids'], 'id' );
86 99 $discount_qty = $this->rule['get_quantity'] ? (int) $this->rule['get_quantity'] : 0; // phpcs:ignore
87 100
88 101 // Default discount for quantities.
89 102 $discount_for_quantities = $min;
90 103
91 - // Apply for the Bulk Discount when max is set.
92 - if ( $max && $quantity >= $max ) {
104 + /**
105 + * Bulk / range capping — only when NOT recursive. Recursive rules ignore
106 + * max: the bundle size is always min, so the qualifying quantity must not
107 + * be capped to max here, otherwise floor( qty / base ) would divide by
108 + * max instead of min and undercount the bundles.
109 + */
110 + if ( ! $recursive && $max && $quantity >= $max ) {
93 111 $discount_for_quantities = $max;
94 112 }
95 113
96 114 // If quantity between min and max then apply discount.
97 - if ( $quantity >= $min && $quantity <= $max ) {
115 + if ( ! $recursive && $quantity >= $min && $quantity <= $max ) {
98 116 $discount_for_quantities = $quantity;
99 117 }
100 118
101 119 // Apply for the Bundle & BOGO Discount when recursive is set.
@@ -117,13 +135,17 @@
117 135 $discount_for_quantities = $discount_qty;
118 136 $multiplier = $discount_qty;
119 137 }
120 138
121 - if ( $recursive ) {
122 - if ( $quantity % $min === 0 || $quantity > $discount_for_quantities ) {
123 - $multiplier = floor( $quantity / $discount_for_quantities );
124 - $discount_for_quantities *= $multiplier;
125 - }
139 + if ( $recursive && $min > 0 && $quantity >= $min ) {
140 + /**
141 + * Recursive: the number of bundles is floor( qty / min ). Divide by
142 + * min, never by $discount_for_quantities — for BuyXGetY the latter
143 + * holds the reward quantity (get_quantity) and would inflate the
144 + * multiplier (e.g. buy 2 get 1 with 2 in cart → 1 bundle, not 2).
145 + */
146 + $multiplier = (int) floor( $quantity / $min );
147 + $discount_for_quantities *= $multiplier;
126 148 }
127 149
128 150 // Limit discount to Min or Max quantity.
129 151 if ( $quantity >= $discount_for_quantities ) {