Skip to content
Open
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
39 changes: 27 additions & 12 deletions Service/Order/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,20 @@ public function execute(ChannableOrderData $orderData): OrderInterface
$order->setTransactionFee($quote->getTransactionFee());

if (isset($orderData['price']['discount']) && !empty((float)$orderData['price']['discount'])) {
$orderCurrency = $orderData['price']['currency'] ?? '';
$discountAmount = abs((float)$orderData['price']['discount']);
$baseDiscountAmount = $this->currencyConverter->convertToBase(
$discountAmount,
$orderCurrency,
$storeId
);
$order->setDiscountDescription($orderData['channel_name']);
$order->setBaseDiscountAmount($baseDiscountAmount * -1);
$order->setDiscountAmount($discountAmount * -1);
$order->setGrandTotal($order->getGrandTotal() - $discountAmount);
$order->setBaseGrandTotal($order->getBaseGrandTotal() - $baseDiscountAmount);
if (!$this->hasItemLevelDiscounts($orderData)) {
$orderCurrency = $orderData['price']['currency'] ?? '';
$discountAmount = abs((float)$orderData['price']['discount']);
$baseDiscountAmount = $this->currencyConverter->convertToBase(
$discountAmount,
$orderCurrency,
$storeId
);
$order->setDiscountDescription($orderData['channel_name']);
$order->setBaseDiscountAmount($baseDiscountAmount * -1);
$order->setDiscountAmount($discountAmount * -1);
$order->setGrandTotal($order->getGrandTotal() - $discountAmount);
$order->setBaseGrandTotal($order->getBaseGrandTotal() - $baseDiscountAmount);
}
}

$store->setCurrentCurrencyCode($store->getBaseCurrencyCode());
Expand Down Expand Up @@ -198,6 +200,19 @@ public function execute(ChannableOrderData $orderData): OrderInterface
}
}

/**
* Check if any product in the order data has an item-level discount.
*/
private function hasItemLevelDiscounts(array $orderData): bool
{
foreach ($orderData['products'] ?? [] as $item) {
if (isset($item['discount']) && (float)$item['discount'] > 0) {
return true;
}
}
return false;
}

/**
* Add shipping info to the checkout-session
*
Expand Down
6 changes: 5 additions & 1 deletion Service/Order/Items/Add.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@ public function execute(Quote $quote, array $data, StoreInterface $store, bool $
throw new CouldNotImportOrder(__($addedItem));
}

$addedItem->setOriginalCustomPrice($price);
$itemDiscount = (isset($item['discount']) && (float)$item['discount'] > 0)
? (float)$item['discount']
: 0.0;

$addedItem->setOriginalCustomPrice($price - $itemDiscount);
$addedItem->setOriginalPrice($channableBasePrice);
$this->itemResourceModel->save($addedItem);
$qty += (int)$item['quantity'];
Expand Down
5 changes: 5 additions & 0 deletions Test/End-2-end/support/services/ChannableApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export default class ChannableApi extends BaseApi {
businessOrder?: boolean;
shipping?: number;
discount?: number;
itemDiscount?: number;
companyName?: string;
channelName?: string;
shipmentMethod?: string;
Expand Down Expand Up @@ -161,6 +162,10 @@ export default class ChannableApi extends BaseApi {
data.products[0].price_tax = priceTax;
}

if (overrides.itemDiscount !== undefined) {
data.products[0].discount = overrides.itemDiscount;
}

if (overrides.orderStatus) {
data.order_status = overrides.orderStatus;
}
Expand Down
37 changes: 37 additions & 0 deletions Test/End-2-end/tests/order/order-import.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,43 @@ const testCases = [
expect(displayedId).toBeTruthy();
},
},
{
title: 'Item-level discount: original price vs discounted price',
config: {},
orderOverrides: { price: 24.99, itemDiscount: 2.50, discount: 2.50 },
assert: async (page, incrementId) => {
// Original price should be the full Channable price (24.99)
const originalPriceStr = await orderViewPage.getOriginalPrice(page);
const originalPrice = parsePrice(originalPriceStr);
expect(originalPrice).toBeCloseTo(24.99, 1);

// Item price should be lower than original (discount applied)
const itemPriceStr = await orderViewPage.getItemPrice(page);
const itemPrice = parsePrice(itemPriceStr);
expect(itemPrice).toBeLessThan(originalPrice);

// Grand total must equal discounted price (22.49), not full price (24.99)
const grandTotalStr = await orderViewPage.getGrandTotal(page);
const grandTotal = parsePrice(grandTotalStr);
expect(grandTotal).toBeCloseTo(22.49, 1);
},
},
{
title: 'Item-level discount: multi-qty grand total',
config: {},
orderOverrides: { price: 24.99, quantity: 3, itemDiscount: 2.50, discount: 7.50 },
assert: async (page, incrementId) => {
// Grand total should be 3 * (24.99 - 2.50) = 67.47
const grandTotalStr = await orderViewPage.getGrandTotal(page);
const grandTotal = parsePrice(grandTotalStr);
expect(grandTotal).toBeCloseTo(67.47, 1);

// Row total must be less than undiscounted (3 * 24.99 = 74.97)
const rowTotalStr = await orderViewPage.getRowTotal(page);
const rowTotal = parsePrice(rowTotalStr);
expect(rowTotal).toBeLessThan(74.97);
},
},
{
title: 'Multi-currency order (PLN)',
config: {
Expand Down
Loading