Skip to content

Commit 0bae91b

Browse files
committed
Fix NoArticleException on product detail page when an out-of-stock variant
1 parent 9ce835b commit 0bae91b

4 files changed

Lines changed: 6 additions & 109 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99
### FIX
1010

1111
- [0007914](https://bugs.oxid-esales.com/view.php?id=7914): Fix Pay upon Invoice (PUI) broken after 2.8.1 security patch. The `_executePayment()` reject guard blocked PUI because it matched `isPayPalPayment()` but was not handled by any prior flow (not a button/proxy/UAPM/checkout payment). Added `gatewaypayment` flag to `PayPalDefinitions` and `isGatewayPayment()` method so PUI correctly falls through to OXID's core `PaymentGateway`.
12-
- [0007915](https://bugs.oxid-esales.com/view.php?id=7915): Fix fatal error "Call to a member function getId() on null" on product detail page when an out-of-stock variant is in the basket. `hasProductVariantInBasket()` delegated to `Basket::getArtStockInBasket()` which calls `getArticle(true)` (buyable-check). For out-of-stock variants this returns null. Replaced with direct basket iteration using `getArticle(false)` to skip the buyable check.
12+
- Fix NoArticleException on product detail page when an out-of-stock variant (configured as "offline when sold out") is still in the basket. The installment banner template called `Basket::getArtStockInBasket()` which internally uses `getArticle(true)` and throws for offline articles. Simplified the banner amount calculation to always add the current product price to the basket total, removing the unnecessary basket iteration. Removed now unused `hasProductVariantInBasket()` method.
1313
- [0007916](https://bugs.oxid-esales.com/view.php?id=7916): Fix orphaned oscpaypal_order rows with OSCPAYPALSTATUS=COMPLETED and empty OXORDERID. When `sess_challenge` was cleared before `captureOrder()` completed (e.g. by a concurrent cancel request), the capture flow proceeded and created tracking records that could not be matched by webhook processing. Added defense-in-depth validation at four levels: `AjaxPaymentController::captureOrder()` now aborts if the shop order cannot be resolved, `PayPalOrderCompletedSubscriber` rejects events with empty shopOrderId, `Payment::trackPayPalOrder()` throws on empty shopOrderId, and `OrderRepository::paypalOrderByOrderIdAndPayPalId()` refuses to create new records with empty shopOrderId.
1414
- [0007917](https://bugs.oxid-esales.com/view.php?id=7917): Fix tracking carrier country not restored on page reload. When a carrier from the "global" country group was saved, the country dropdown was reset to the order's shipping/billing country instead. Added `getCountryCodeByCarrierKey()` to `PayPalTrackingCarrierList` and `getEffectiveTrackingCountryCode()` to `OrderMain` to resolve the saved carrier's country and pre-select it in the dropdown.
1515

src/Model/Basket.php

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -245,31 +245,6 @@ public function getPayPalCheckoutRoundDiff()
245245
return $result;
246246
}
247247

248-
/**
249-
* Check if variants of the given product are already in the basket
250-
* @param \OxidEsales\Eshop\Application\Model\Article $product
251-
* @return bool
252-
*/
253-
public function hasProductVariantInBasket(\OxidEsales\Eshop\Application\Model\Article $product)
254-
{
255-
$variantIds = $product->getVariantIds();
256-
if (empty($variantIds)) {
257-
return false;
258-
}
259-
260-
$variantIdMap = array_flip($variantIds);
261-
foreach ($this->getContents() as $basketItem) {
262-
// Use getArticle(false) to skip the buyable check – out-of-stock
263-
// variants that are still in the basket must not cause a fatal error.
264-
$article = $basketItem->getArticle(false);
265-
if ($article && isset($variantIdMap[$article->getId()])) {
266-
return true;
267-
}
268-
}
269-
270-
return false;
271-
}
272-
273248
/**
274249
* add a ShippingPrice for PPExpress if it is not defined before to prevent overcharge.
275250
* @param float $defaultShippingPriceExpress

tests/Unit/Model/BasketTest.php

Lines changed: 0 additions & 76 deletions
This file was deleted.

views/blocks/page/details/inc/productmain.tpl

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
[{assign var="bannerAmount" value=$oxcmp_basket->getNettoSum()}]
66
[{/if}]
77

8-
[{if ($oxcmp_basket->getArtStockInBasket($oDetailsProduct->getId()) === 0) && !$oxcmp_basket->hasProductVariantInBasket($oDetailsProduct)}]
9-
[{assign var="oPrice" value=$oDetailsProduct->getPrice()}]
10-
[{if $oDetailsProduct->isParentNotBuyable()}]
11-
[{assign var="oPrice" value=$oDetailsProduct->getVarMinPrice()}]
12-
[{/if}]
13-
[{assign var="productPrice" value=$oPrice->getPrice()}]
14-
[{assign var="bannerAmount" value=$bannerAmount+$productPrice}]
8+
[{assign var="oPrice" value=$oDetailsProduct->getPrice()}]
9+
[{if $oDetailsProduct->isParentNotBuyable()}]
10+
[{assign var="oPrice" value=$oDetailsProduct->getVarMinPrice()}]
1511
[{/if}]
12+
[{assign var="productPrice" value=$oPrice->getPrice()}]
13+
[{assign var="bannerAmount" value=$bannerAmount+$productPrice}]
1614
[{include file="modules/osc/paypal/installment_banners.tpl" amount=$bannerAmount selector=$oViewConf->getPayPalCheckoutBannerProductDetailsPageSelector()}]
1715
[{/if}]

0 commit comments

Comments
 (0)