Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 45 additions & 11 deletions js/price/ppom-price.js
Original file line number Diff line number Diff line change
Expand Up @@ -1022,17 +1022,49 @@ function ppom_update_get_prices() {
const apply_as_discount = ppom_pricematrix_discount == 'on' ? true : false;

if ( ppom_pricematrix !== undefined ) {
jQuery.each( JSON.parse( ppom_pricematrix ), function ( range, meta ) {
const matrixData = JSON.parse(ppom_pricematrix);
const product_qty = parseInt(ppom_get_order_quantity(), 10);

// Pre-process keys ONCE (fix performance + ordering issue)
const parsedKeys = Object.keys(matrixData).map((range) => {
if (range.includes('-')) {
const [start, end] = range.split('-').map(Number);
return { type: 'range', start, end, key: range };
} else {
return { type: 'single', value: Number(range), key: range };
}
});

parsedKeys.sort((a, b) => {
const aVal = a.type === 'range' ? a.start : a.value;
const bVal = b.type === 'range' ? b.start : b.value;
return aVal - bVal;
});

const firstKey = parsedKeys[0]?.key;
const lastKey = parsedKeys[parsedKeys.length - 1]?.key;

jQuery.each(matrixData, function (range, meta) {
const option_price = {};
let isMatch = false;

if (range.indexOf('-') !== -1) {
const [range_from, range_to] = range.split('-').map(Number);

const range_break = range.split( '-' );
const range_from = parseInt( range_break[ 0 ] );
const range_to = parseInt( range_break[ 1 ] );
const product_qty = ppom_get_order_quantity();
if (product_qty >= range_from && product_qty <= range_to) {
isMatch = true;
}
} else {
const value = Number(range);

// console.log(range, meta);
if (range === firstKey && product_qty <= value) {
isMatch = true;
} else if (range === lastKey && product_qty >= value) {
isMatch = true;
}
}

if ( product_qty >= range_from && product_qty <= range_to ) {
if (isMatch) {
option_price.label = meta.label;
option_price.price = meta.price;
option_price.percent = meta.percent;
Expand All @@ -1041,11 +1073,13 @@ function ppom_update_get_prices() {
? 'matrix_discount'
: 'matrix';
option_price.data_name = ppom_pricematrix_id;
option_price.matrix_fixed =
meta.matrix_fixed == 'on' ? true : false;
options_price_added.push( option_price );
option_price.matrix_fixed = meta.matrix_fixed === 'on';

options_price_added.push(option_price);

return false;
}
} );
});
}

// Variation quantities
Expand Down
23 changes: 16 additions & 7 deletions src/Support/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -1514,16 +1514,25 @@ public static function extract_matrix_by_quantity( $quantities_field, $product,
return $matrix;
}

$quantity = intval( $quantity );
foreach ( $ranges as $range => $data ) {

$range_array = explode( '-', $range );
$range_start = $range_array[0];
$range_end = $range_array[1];
if ( strpos( $range, '-' ) !== false ) {
list( $start, $end ) = array_map( 'intval', explode( '-', $range ) );
if ( $quantity >= $start && $quantity <= $end ) {
$matrix = $data;
break;
}
} else {
$value = intval( $range );

$quantity = intval( $quantity );
if ( $quantity >= $range_start && $quantity <= $range_end ) {
$matrix = $data;
break;
if ( $range === array_key_first( $ranges ) && $quantity <= $value ) {
$matrix = $data;
break;
} elseif ( $range === array_key_last( $ranges ) && $quantity >= $value ) {
$matrix = $data;
break;
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/Validation/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,11 @@ public static function get_product_limits( $product_id, $variation_id ) {
$first_range = reset( $ranges );
$qty_ranges = explode( '-', $first_range['raw'] );
$min_quantity = $qty_ranges[0];

// If first options is not in range format, set min quantity to 1.
if ( ! isset( $qty_ranges[1] ) ) {
$min_quantity = 1;
}
}
}

Expand All @@ -329,7 +334,7 @@ public static function get_product_limits( $product_id, $variation_id ) {

$last_range = end( $ranges );
$qty_ranges = explode( '-', $last_range['raw'] );
$max_quantity = $qty_ranges[1];
$max_quantity = isset( $qty_ranges[1] ) ? $qty_ranges[1] : -1;
}
}

Expand Down
20 changes: 14 additions & 6 deletions tests/unit/test-checkout-lifecycle.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,19 @@ public function testWooCommerceGetCartItemFromSessionRecalculatesMatrixPriceWhen
'price_matrix',
array(
array(
'option' => '1-2',
'option' => '5',
'price' => '12',
'label' => 'Low quantity',
'id' => 'low_qty',
),
array(
'option' => '3-5',
'option' => '5-10',
'price' => '10',
'label' => 'Range quantity',
'id' => 'range_qty',
),
array(
'option' => '11',
'price' => '8',
'label' => 'High quantity',
'id' => 'high_qty',
Expand All @@ -279,11 +285,13 @@ public function testWooCommerceGetCartItemFromSessionRecalculatesMatrixPriceWhen
$product->get_id()
);

$initial = $this->restore_cart_item_from_session( wc_get_product( $product->get_id() ), array(), 1 );
$updated = $this->restore_cart_item_from_session( wc_get_product( $product->get_id() ), array(), 3 );
$low_quantity = $this->restore_cart_item_from_session( wc_get_product( $product->get_id() ), array(), 3 );
$range_quantity = $this->restore_cart_item_from_session( wc_get_product( $product->get_id() ), array(), 7 );
$high_quantity = $this->restore_cart_item_from_session( wc_get_product( $product->get_id() ), array(), 15 );

$this->assertSame( 12.0, (float) $initial['data']->get_price() );
$this->assertSame( 8.0, (float) $updated['data']->get_price() );
$this->assertSame( 12.0, (float) $low_quantity['data']->get_price() );
$this->assertSame( 10.0, (float) $range_quantity['data']->get_price() );
$this->assertSame( 8.0, (float) $high_quantity['data']->get_price() );
}

/**
Expand Down
Loading