@@ -104,7 +104,35 @@ public function getAvailableNumber($number, ShopContextInterface $context, $sele
104104 return $ selected ;
105105 }
106106
107- return $ number ;
107+ if ($ this ->isNumberAvailable ($ number )) {
108+ return $ number ;
109+ }
110+
111+ $ selected = $ this ->findFallbackById ($ productId );
112+ if (!$ selected ) {
113+ throw new \RuntimeException ("No active product variant found " );
114+ }
115+
116+ return $ selected ;
117+ }
118+
119+ /**
120+ * @param int $productId
121+ * @return string|false
122+ */
123+ private function findFallbackById ($ productId )
124+ {
125+ $ selected = $ this ->getMainVariantNumberById ($ productId );
126+ if ($ selected ) {
127+ return $ selected ;
128+ }
129+
130+ $ selected = $ this ->getAvailableFallbackVariant ($ productId );
131+ if ($ selected ) {
132+ return $ selected ;
133+ }
134+
135+ return $ this ->getFallbackVariant ($ productId );
108136 }
109137
110138 /**
@@ -123,7 +151,7 @@ private function getProductIdByNumber($number)
123151
124152 /**@var $statement \PDOStatement*/
125153 $ statement = $ query ->execute ();
126-
154+
127155 return $ statement ->fetch (\PDO ::FETCH_COLUMN );
128156 }
129157
@@ -158,17 +186,110 @@ private function getNumberBySelection($productId, array $selection)
158186 $ query ->setParameter (': ' . $ alias , (int ) $ optionId );
159187 }
160188
189+ if ($ this ->config ->get ('hideNoInStock ' )) {
190+ $ query ->innerJoin ('variant ' , 's_articles ' , 'product ' , 'product.id = variant.articleID ' );
191+ $ query ->andWhere ('(product.laststock * variant.instock) >= (product.laststock * variant.minpurchase) ' );
192+ }
193+
161194 /**@var $statement \Doctrine\DBAL\Driver\ResultStatement */
162195 $ statement = $ query ->execute ();
163196
164197 return $ statement ->fetch (\PDO ::FETCH_COLUMN );
165198 }
166199
200+ /**
201+ * @param string $number
202+ * @return boolean
203+ */
204+ private function isNumberAvailable ($ number )
205+ {
206+ $ query = $ this ->getProductNumberQuery ();
207+ $ query ->where ('variant.ordernumber = :number ' )
208+ ->andWhere ('(product.laststock * variant.instock) >= (product.laststock * variant.minpurchase) ' )
209+ ->setParameter (':number ' , $ number );
210+
211+ $ statement = $ query ->execute ();
212+ $ selected = $ statement ->fetch (\PDO ::FETCH_COLUMN );
213+
214+ return (bool ) $ selected ;
215+ }
216+
217+ /**
218+ * @param int $productId
219+ * @return string|false
220+ */
221+ private function getMainVariantNumberById ($ productId )
222+ {
223+ $ query = $ this ->getProductNumberQuery ();
224+ $ query ->where ('variant.id = product.main_detail_id ' )
225+ ->andWhere ('product.id = :productId ' )
226+ ->andWhere ('(product.laststock * variant.instock) >= (product.laststock * variant.minpurchase) ' )
227+ ->setParameter (':productId ' , $ productId );
228+
229+ $ statement = $ query ->execute ();
230+ $ selected = $ statement ->fetch (\PDO ::FETCH_COLUMN );
231+
232+ return $ selected ;
233+ }
234+
235+ /**
236+ * Returns the first active variant number
237+ *
238+ * @param int $productId
239+ * @return string|false
240+ */
241+ private function getFallbackVariant ($ productId )
242+ {
243+ $ query = $ this ->getProductNumberQuery ();
244+
245+ $ query ->andWhere ('product.id = :productId ' );
246+ $ query ->setMaxResults (1 );
247+ $ query ->setParameter (':productId ' , $ productId );
248+
249+ $ statement = $ query ->execute ();
250+ $ selected = $ statement ->fetch (\PDO ::FETCH_COLUMN );
251+
252+ return $ selected ;
253+ }
254+
255+ /**
256+ * Returns the first active variant number that is available for purchase
257+ *
258+ * @param int $productId
259+ * @return string|false
260+ */
261+ private function getAvailableFallbackVariant ($ productId )
262+ {
263+ $ query = $ this ->getProductNumberQuery ();
264+
265+ $ query ->andWhere ('product.id = :productId ' );
266+ $ query ->andWhere ('(product.laststock * variant.instock) >= (product.laststock * variant.minpurchase) ' );
267+ $ query ->setMaxResults (1 );
268+ $ query ->setParameter (':productId ' , $ productId );
269+
270+ $ statement = $ query ->execute ();
271+ $ selected = $ statement ->fetch (\PDO ::FETCH_COLUMN );
272+
273+ return $ selected ;
274+ }
275+
276+ /**
277+ * @return \Doctrine\DBAL\Query\QueryBuilder
278+ */
279+ private function getProductNumberQuery ()
280+ {
281+ $ query = $ this ->connection ->createQueryBuilder ();
282+ $ query ->select (['variant.ordernumber ' ]);
283+ $ query ->from ('s_articles_details ' , 'variant ' );
284+ $ query ->innerJoin ('variant ' , 's_articles ' , 'product ' , 'product.id = variant.articleID AND variant.active = 1 ' );
285+ $ query ->setMaxResults (1 );
286+ return $ query ;
287+ }
288+
167289 /**
168290 * Validates if the product is available in the current shop
169291 * @param int $productId
170292 * @param Shop $shop
171- * @return int
172293 */
173294 private function isProductAvailableInShop ($ productId , $ shop )
174295 {
0 commit comments