| @@ -111,11 +111,36 @@ | ||
| 111 | 111 | if ( empty( $discounts ) ) { |
| 112 | 112 | return $price; |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | + /** | |
| 116 | + * Only amounts the product can actually carry take part in the choice. | |
| 117 | + * | |
| 118 | + * A flat amount larger than the price cannot be applied, and it used | |
| 119 | + * to win the min/max selection anyway and then be rejected by the | |
| 120 | + * guard below, leaving the product at full price even though another | |
| 121 | + * campaign offered a discount that would have fitted. With a 70% | |
| 122 | + * campaign and a 50.00 campaign, everything priced under 50.00 was | |
| 123 | + * discounted by nothing at all while a 50.00 product went free. | |
| 124 | + * | |
| 125 | + * Dropping the ones that do not fit first means `max` picks the | |
| 126 | + * largest discount that can be given rather than the largest that was | |
| 127 | + * offered, which is what asking for the maximum discount means. | |
| 128 | + */ | |
| 129 | + $applicable = array_filter( | |
| 130 | + $discounts, | |
| 131 | + static function ( $amount ) use ( $price ) { | |
| 132 | + return (float) $amount <= (float) $price; | |
| 133 | + } | |
| 134 | + ); | |
| 135 | + | |
| 136 | + if ( empty( $applicable ) ) { | |
| 137 | + return $price; | |
| 138 | + } | |
| 139 | + | |
| 115 | 140 | // Pick the winning discount amount, then map it back to the campaign that produced it. |
| 116 | - $discounted_amount = $this->min_max_average( array_values( $discounts ) ); | |
| 117 | - $this->applied_campaign_id = (int) array_search( $discounted_amount, $discounts, true ); | |
| 141 | + $discounted_amount = $this->min_max_average( array_values( $applicable ) ); | |
| 142 | + $this->applied_campaign_id = (int) array_search( $discounted_amount, $applicable, true ); | |
| 118 | 143 | |
| 119 | 144 | if ( $discounted_amount <= $price ) { |
| 120 | 145 | // Get an applied campaign from DiscountLimit class. |
| 121 | 146 | ( new UserLimit )->disco_start_session_on_checkout( $this->applied_campaign_id ); |