1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Copyright © 2016-present Spryker Systems GmbH. All rights reserved. |
||
5 | * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. |
||
6 | */ |
||
7 | |||
8 | namespace SprykerTest\Zed\Availability\Business; |
||
9 | |||
10 | use ArrayObject; |
||
11 | use Codeception\Test\Unit; |
||
12 | use Generated\Shared\Transfer\CheckoutResponseTransfer; |
||
13 | use Generated\Shared\Transfer\DynamicEntityPostEditRequestTransfer; |
||
14 | use Generated\Shared\Transfer\ItemTransfer; |
||
15 | use Generated\Shared\Transfer\ProductAvailabilityCriteriaTransfer; |
||
16 | use Generated\Shared\Transfer\ProductConcreteTransfer; |
||
17 | use Generated\Shared\Transfer\QuoteTransfer; |
||
18 | use Generated\Shared\Transfer\RawDynamicEntityTransfer; |
||
19 | use Generated\Shared\Transfer\SellableItemsResponseTransfer; |
||
20 | use Generated\Shared\Transfer\StockProductTransfer; |
||
21 | use Generated\Shared\Transfer\StoreTransfer; |
||
22 | use Generated\Shared\Transfer\WishlistItemTransfer; |
||
23 | use Orm\Zed\Availability\Persistence\SpyAvailability; |
||
24 | use Orm\Zed\Availability\Persistence\SpyAvailabilityAbstractQuery; |
||
25 | use Orm\Zed\Availability\Persistence\SpyAvailabilityQuery; |
||
26 | use Orm\Zed\Product\Persistence\SpyProductAbstractQuery; |
||
27 | use Orm\Zed\Product\Persistence\SpyProductQuery; |
||
28 | use Orm\Zed\Stock\Persistence\SpyStockProduct; |
||
29 | use Orm\Zed\Stock\Persistence\SpyStockProductQuery; |
||
30 | use Orm\Zed\Stock\Persistence\SpyStockQuery; |
||
31 | use Spryker\DecimalObject\Decimal; |
||
32 | use Spryker\Zed\Availability\AvailabilityDependencyProvider; |
||
33 | use Spryker\Zed\Availability\Business\AvailabilityBusinessFactory; |
||
34 | use Spryker\Zed\Availability\Business\AvailabilityFacade; |
||
35 | use Spryker\Zed\Availability\Dependency\Facade\AvailabilityToStockFacadeInterface; |
||
36 | use Spryker\Zed\AvailabilityExtension\Dependency\Plugin\AvailabilityStrategyPluginInterface; |
||
37 | use Spryker\Zed\AvailabilityExtension\Dependency\Plugin\BatchAvailabilityStrategyPluginInterface; |
||
38 | use Spryker\Zed\Kernel\Container; |
||
39 | |||
40 | /** |
||
41 | * Auto-generated group annotations |
||
42 | * |
||
43 | * @group SprykerTest |
||
44 | * @group Zed |
||
45 | * @group Availability |
||
46 | * @group Business |
||
47 | * @group Facade |
||
48 | * @group AvailabilityFacadeTest |
||
49 | * Add your own group annotations below this line |
||
50 | */ |
||
51 | class AvailabilityFacadeTest extends Unit |
||
52 | { |
||
53 | /** |
||
54 | * @var string |
||
55 | */ |
||
56 | protected const ABSTRACT_SKU = '123_availability_test'; |
||
57 | |||
58 | /** |
||
59 | * @var string |
||
60 | */ |
||
61 | protected const CONCRETE_SKU = '123_availability_test-concrete'; |
||
62 | |||
63 | /** |
||
64 | * @var int |
||
65 | */ |
||
66 | protected const ID_STORE = 1; |
||
67 | |||
68 | /** |
||
69 | * @var string |
||
70 | */ |
||
71 | protected const STORE_NAME_DE = 'DE'; |
||
72 | |||
73 | /** |
||
74 | * @var string |
||
75 | */ |
||
76 | protected const STORE_NAME_AT = 'AT'; |
||
77 | |||
78 | /** |
||
79 | * @var string |
||
80 | */ |
||
81 | protected const COL_QUANTITY = 'quantity'; |
||
82 | |||
83 | /** |
||
84 | * @var string |
||
85 | */ |
||
86 | protected const STOCK_PRODUCT_TABLE_NAME = 'spy_stock_product'; |
||
87 | |||
88 | /** |
||
89 | * @var string |
||
90 | */ |
||
91 | protected const TEST_TABLE_NAME = 'spy_test'; |
||
92 | |||
93 | /** |
||
94 | * @var string |
||
95 | */ |
||
96 | protected const FK_PRODUCT = 'fk_product'; |
||
97 | |||
98 | /** |
||
99 | * @var \SprykerTest\Zed\Availability\AvailabilityBusinessTester |
||
100 | */ |
||
101 | protected $tester; |
||
102 | |||
103 | /** |
||
104 | * @return void |
||
105 | */ |
||
106 | public function testIsProductSellableWhenNeverOutOfStockShouldReturnSuccess(): void |
||
107 | { |
||
108 | // Arrange |
||
109 | $this->tester->haveProduct([ProductConcreteTransfer::SKU => static::CONCRETE_SKU]); |
||
110 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
111 | $this->createProductWithStock( |
||
112 | static::ABSTRACT_SKU, |
||
113 | static::CONCRETE_SKU, |
||
114 | ['is_never_out_of_stock' => true], |
||
115 | $storeTransfer, |
||
116 | ); |
||
117 | |||
118 | // Act |
||
119 | $isProductSellable = $this->getAvailabilityFacade() |
||
120 | ->isProductSellableForStore(static::CONCRETE_SKU, new Decimal(1), $storeTransfer); |
||
121 | |||
122 | // Assert |
||
123 | $this->assertTrue($isProductSellable); |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * @return void |
||
128 | */ |
||
129 | public function testIsProductSellableWhenStockIsEmptyShouldReturnFailure(): void |
||
130 | { |
||
131 | // Arrange |
||
132 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
133 | $this->createProductWithStock( |
||
134 | static::ABSTRACT_SKU, |
||
135 | static::CONCRETE_SKU, |
||
136 | ['quantity' => 0], |
||
137 | $storeTransfer, |
||
138 | ); |
||
139 | |||
140 | // Act |
||
141 | $isProductSellable = $this->getAvailabilityFacade() |
||
142 | ->isProductSellableForStore(static::CONCRETE_SKU, new Decimal(1), $storeTransfer); |
||
143 | |||
144 | // Assert |
||
145 | $this->assertFalse($isProductSellable); |
||
146 | } |
||
147 | |||
148 | /** |
||
149 | * @return void |
||
150 | */ |
||
151 | public function testIsProductSellableWhenStockFulfilledShouldReturnSuccess(): void |
||
152 | { |
||
153 | // Arrange |
||
154 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
155 | $this->createProductWithStock( |
||
156 | static::ABSTRACT_SKU, |
||
157 | static::CONCRETE_SKU, |
||
158 | ['quantity' => 5], |
||
159 | $storeTransfer, |
||
160 | ); |
||
161 | |||
162 | // Act |
||
163 | $isProductSellable = $this->getAvailabilityFacade() |
||
164 | ->isProductSellableForStore(static::CONCRETE_SKU, new Decimal(1), $storeTransfer); |
||
165 | |||
166 | // Assert |
||
167 | $this->assertTrue($isProductSellable); |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * @dataProvider provideTestDecimalQuantity |
||
172 | * |
||
173 | * @param \Spryker\DecimalObject\Decimal $quantity |
||
174 | * |
||
175 | * @return void |
||
176 | */ |
||
177 | public function testCalculateStockForProductShouldReturnPersistedStock(Decimal $quantity): void |
||
178 | { |
||
179 | // Arrange |
||
180 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
181 | $this->createProductWithStock( |
||
182 | static::ABSTRACT_SKU, |
||
183 | static::CONCRETE_SKU, |
||
184 | ['quantity' => $quantity->toString()], |
||
185 | $storeTransfer, |
||
186 | ); |
||
187 | |||
188 | // Act |
||
189 | $calculatedQuantity = $this->getAvailabilityFacade() |
||
190 | ->calculateAvailabilityForProductWithStore(static::CONCRETE_SKU, $storeTransfer); |
||
191 | |||
192 | // Assert |
||
193 | $this->assertTrue($calculatedQuantity->equals($quantity)); |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * @return array |
||
198 | */ |
||
199 | public function provideTestDecimalQuantity(): array |
||
200 | { |
||
201 | return [ |
||
202 | 'int stock' => [new Decimal(5)], |
||
203 | 'float stock' => [new Decimal(5.5)], |
||
204 | ]; |
||
205 | } |
||
206 | |||
207 | /** |
||
208 | * @return void |
||
209 | */ |
||
210 | public function testCheckAvailabilityPreConditionShouldNotWriteErrorsWhenAvailabilityIsSatisfied(): void |
||
211 | { |
||
212 | // Arrange |
||
213 | $checkoutResponseTransfer = new CheckoutResponseTransfer(); |
||
214 | $quoteTransfer = $this->createQuoteTransfer(); |
||
215 | $this->createProductWithStock( |
||
216 | static::ABSTRACT_SKU, |
||
217 | static::CONCRETE_SKU, |
||
218 | [static::COL_QUANTITY => 5], |
||
219 | $quoteTransfer->getStore(), |
||
220 | ); |
||
221 | |||
222 | // Act |
||
223 | $this->tester->getFacade() |
||
224 | ->checkoutAvailabilityPreCondition($quoteTransfer, $checkoutResponseTransfer); |
||
225 | |||
226 | // Assert |
||
227 | $this->assertEmpty($checkoutResponseTransfer->getErrors()); |
||
228 | } |
||
229 | |||
230 | /** |
||
231 | * @return void |
||
232 | */ |
||
233 | public function testCheckAvailabilityPreConditionShouldWriteErrorWhenAvailabilityIsNotSatisfied(): void |
||
234 | { |
||
235 | // Arrange |
||
236 | $checkoutResponseTransfer = new CheckoutResponseTransfer(); |
||
237 | $quoteTransfer = $this->createQuoteTransfer(); |
||
238 | $this->createProductWithStock( |
||
239 | static::ABSTRACT_SKU, |
||
240 | static::CONCRETE_SKU, |
||
241 | [static::COL_QUANTITY => 0], |
||
242 | $quoteTransfer->getStore(), |
||
243 | ); |
||
244 | |||
245 | // Act |
||
246 | $this->tester->getFacade() |
||
247 | ->checkoutAvailabilityPreCondition($quoteTransfer, $checkoutResponseTransfer); |
||
248 | |||
249 | // Assert |
||
250 | $this->assertCount(1, $checkoutResponseTransfer->getErrors()); |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * @return void |
||
255 | */ |
||
256 | public function testCheckAvailabilityPreConditionExecutesAvailabilityStrategyPluginStack(): void |
||
257 | { |
||
258 | // Arrange |
||
259 | $quoteTransfer = $this->createQuoteTransfer(); |
||
260 | $this->createProductWithStock( |
||
261 | static::ABSTRACT_SKU, |
||
262 | static::CONCRETE_SKU, |
||
263 | [static::COL_QUANTITY => 1], |
||
264 | $quoteTransfer->getStore(), |
||
265 | ); |
||
266 | |||
267 | $availabilityStrategyPluginMock = $this->getMockBuilder(AvailabilityStrategyPluginInterface::class) |
||
268 | ->getMock(); |
||
269 | |||
270 | $availabilityStrategyPluginMock |
||
271 | ->expects($this->once()) |
||
272 | ->method('isApplicable') |
||
273 | ->willReturn(true); |
||
274 | |||
275 | $availabilityStrategyPluginMock |
||
276 | ->expects($this->once()) |
||
277 | ->method('findProductConcreteAvailabilityForStore'); |
||
278 | |||
279 | $this->tester->setDependency(AvailabilityDependencyProvider::PLUGINS_AVAILABILITY_STRATEGY, [ |
||
280 | $availabilityStrategyPluginMock, |
||
281 | ]); |
||
282 | |||
283 | // Act |
||
284 | $this->tester->getFacade() |
||
285 | ->checkoutAvailabilityPreCondition($quoteTransfer, new CheckoutResponseTransfer()); |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * @return void |
||
290 | */ |
||
291 | public function testCheckAvailabilityPreConditionWillExecuteBatchAvailabilityStrategyPlugins(): void |
||
292 | { |
||
293 | // Arrange |
||
294 | $checkoutResponseTransfer = new CheckoutResponseTransfer(); |
||
295 | $quoteTransfer = $this->createQuoteTransfer(); |
||
296 | $this->createProductWithStock( |
||
297 | static::ABSTRACT_SKU, |
||
298 | static::CONCRETE_SKU, |
||
299 | [static::COL_QUANTITY => 0], |
||
300 | $quoteTransfer->getStore(), |
||
301 | ); |
||
302 | |||
303 | $batchAvailabilityStrategyPluginMock = $this->getMockBuilder(BatchAvailabilityStrategyPluginInterface::class) |
||
304 | ->getMock(); |
||
305 | |||
306 | $batchAvailabilityStrategyPluginMock |
||
307 | ->expects($this->once()) |
||
308 | ->method('findItemsAvailabilityForStore') |
||
309 | ->willReturn((new SellableItemsResponseTransfer())->setSellableItemResponses(new ArrayObject())); |
||
310 | |||
311 | $this->tester->setDependency(AvailabilityDependencyProvider::PLUGINS_BATCH_AVAILABILITY_STRATEGY, [ |
||
312 | $batchAvailabilityStrategyPluginMock, |
||
313 | ]); |
||
314 | |||
315 | // Act |
||
316 | $this->tester->getFacade() |
||
317 | ->checkoutAvailabilityPreCondition($quoteTransfer, $checkoutResponseTransfer); |
||
318 | |||
319 | // Assert |
||
320 | $this->assertEmpty($checkoutResponseTransfer->getErrors()); |
||
321 | } |
||
322 | |||
323 | /** |
||
324 | * @return void |
||
325 | */ |
||
326 | public function testUpdateAvailabilityShouldStoreNewQuantity(): void |
||
327 | { |
||
328 | // Arrange |
||
329 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
330 | $stockProductEntity = $this->createProductWithStock( |
||
331 | static::ABSTRACT_SKU, |
||
332 | static::CONCRETE_SKU, |
||
333 | ['quantity' => 5], |
||
334 | $storeTransfer, |
||
335 | ); |
||
336 | |||
337 | $stockProductEntity->setQuantity(50); |
||
338 | $stockProductEntity->save(); |
||
339 | |||
340 | // Act |
||
341 | $this->getAvailabilityFacade()->updateAvailability(static::CONCRETE_SKU); |
||
342 | |||
343 | // Assert |
||
344 | $availabilityEntity = $this->tester->getAvailabilityQuery()->findOneBySku(static::CONCRETE_SKU); |
||
345 | $this->assertNotNull($availabilityEntity); |
||
346 | $this->assertSame(50, (new Decimal($availabilityEntity->getQuantity()))->toInt()); |
||
347 | |||
348 | $availabilityAbstractEntity = $this->tester->getAvailabilityAbstractQuery()->findOneByAbstractSku(static::ABSTRACT_SKU); |
||
349 | $this->assertNotNull($availabilityAbstractEntity); |
||
350 | $this->assertSame(50, (new Decimal($availabilityAbstractEntity->getQuantity()))->toInt()); |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * @return void |
||
355 | */ |
||
356 | public function testUpdateAvailabilityWhenItsEmptyShouldStoreNewQuantity(): void |
||
357 | { |
||
358 | // Arrange |
||
359 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
360 | $this->createProductWithStock( |
||
361 | static::ABSTRACT_SKU, |
||
362 | static::CONCRETE_SKU, |
||
363 | ['quantity' => 50], |
||
364 | $storeTransfer, |
||
365 | ); |
||
366 | $this->createProductAvailability(static::ABSTRACT_SKU, static::CONCRETE_SKU, new Decimal(0), $storeTransfer); |
||
367 | |||
368 | // Act |
||
369 | $this->getAvailabilityFacade()->updateAvailability(static::CONCRETE_SKU); |
||
370 | |||
371 | // Assert |
||
372 | $availabilityEntity = $this->tester->getAvailabilityQuery()->findOneBySku(static::CONCRETE_SKU); |
||
373 | $this->assertSame(50, (new Decimal($availabilityEntity->getQuantity()))->toInt()); |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * @return void |
||
378 | */ |
||
379 | public function testUpdateAvailabilityWhenSetToEmptyShouldStoreEmptyQuantity(): void |
||
380 | { |
||
381 | // Arrange |
||
382 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
383 | $productTransfer = $this->tester->haveProduct(); |
||
384 | $this->tester->haveProductInStockForStore($storeTransfer, [ |
||
385 | StockProductTransfer::SKU => $productTransfer->getSku(), |
||
386 | StockProductTransfer::QUANTITY => 0, |
||
387 | StockProductTransfer::IS_NEVER_OUT_OF_STOCK => false, |
||
388 | ]); |
||
389 | |||
390 | // Act |
||
391 | $this->getAvailabilityFacade()->updateAvailability($productTransfer->getSku()); |
||
392 | |||
393 | // Assert |
||
394 | $availabilityEntity = $this->tester->getAvailabilityQuery()->findOneBySku($productTransfer->getSku()); |
||
395 | $this->assertNotNull($availabilityEntity); |
||
396 | $this->assertSame(0, (new Decimal($availabilityEntity->getQuantity()))->toInt()); |
||
397 | $availabilityAbstractEntity = $this->tester->getAvailabilityAbstractQuery()->findOneByAbstractSku($productTransfer->getAbstractSku()); |
||
398 | $this->assertNotNull($availabilityAbstractEntity); |
||
399 | $this->assertSame(0, (new Decimal($availabilityAbstractEntity->getQuantity()))->toInt()); |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * @return void |
||
404 | */ |
||
405 | public function testUpdateAvailabilityShouldStoreEmptyQuantityWhenStockProductDoesNotHaveRelationToSameStore(): void |
||
406 | { |
||
407 | // Arrange |
||
408 | $storeDeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE], false); |
||
409 | $storeAtTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_AT], false); |
||
410 | $productTransfer = $this->tester->haveProduct(); |
||
411 | $this->tester->haveProductInStockForStore($storeDeTransfer, [ |
||
412 | StockProductTransfer::SKU => $productTransfer->getSku(), |
||
413 | StockProductTransfer::QUANTITY => 10, |
||
414 | StockProductTransfer::IS_NEVER_OUT_OF_STOCK => false, |
||
415 | ]); |
||
416 | $this->createProductAvailability( |
||
417 | $productTransfer->getAbstractSkuOrFail(), |
||
418 | $productTransfer->getSkuOrFail(), |
||
419 | new Decimal(10), |
||
420 | $storeDeTransfer, |
||
421 | ); |
||
422 | $this->createProductAvailability( |
||
423 | $productTransfer->getAbstractSkuOrFail(), |
||
424 | $productTransfer->getSkuOrFail(), |
||
425 | new Decimal(10), |
||
426 | $storeAtTransfer, |
||
427 | ); |
||
428 | |||
429 | // Act |
||
430 | $this->getAvailabilityFacade()->updateAvailability($productTransfer->getSku()); |
||
431 | |||
432 | // Assert |
||
433 | $availabilityDeEntity = $this->tester->findAvailabilityConcreteForStore( |
||
434 | $productTransfer->getSkuOrFail(), |
||
435 | $storeDeTransfer->getIdStoreOrFail(), |
||
436 | ); |
||
437 | $this->assertNotNull($availabilityDeEntity); |
||
438 | $this->assertTrue((new Decimal(10))->equals($availabilityDeEntity->getQuantity())); |
||
439 | |||
440 | $availabilityAtEntity = $this->tester->findAvailabilityConcreteForStore( |
||
441 | $productTransfer->getSkuOrFail(), |
||
442 | $storeAtTransfer->getIdStoreOrFail(), |
||
443 | ); |
||
444 | $this->assertNotNull($availabilityAtEntity); |
||
445 | $this->assertTrue((new Decimal(0))->equals($availabilityAtEntity->getQuantity())); |
||
446 | } |
||
447 | |||
448 | /** |
||
449 | * @return void |
||
450 | */ |
||
451 | public function testFindProductAbstractAvailabilityForStoreWithCachedAvailability(): void |
||
452 | { |
||
453 | // Arrange |
||
454 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
455 | $productTransfer = $this->tester->haveProduct([], ['sku' => static::ABSTRACT_SKU]); |
||
456 | $this->tester->haveAvailabilityAbstract($productTransfer, new Decimal(2), $storeTransfer->getIdStore()); |
||
457 | |||
458 | // Act |
||
459 | $productAbstractAvailabilityTransfer = $this->getAvailabilityFacade() |
||
460 | ->findOrCreateProductAbstractAvailabilityBySkuForStore( |
||
461 | $productTransfer->getAbstractSku(), |
||
462 | $storeTransfer, |
||
463 | ); |
||
464 | |||
465 | // Assert |
||
466 | $this->assertNotNull($productAbstractAvailabilityTransfer); |
||
467 | $this->assertSame(2, $productAbstractAvailabilityTransfer->getAvailability()->trim()->toInt()); |
||
468 | } |
||
469 | |||
470 | /** |
||
471 | * @return void |
||
472 | */ |
||
473 | public function testFindProductAbstractAvailabilityForStoreWithInvalidSku(): void |
||
474 | { |
||
475 | // Arrange |
||
476 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
477 | |||
478 | // Act |
||
479 | $productAbstractAvailabilityTransfer = $this->getAvailabilityFacade() |
||
480 | ->findOrCreateProductAbstractAvailabilityBySkuForStore( |
||
481 | 'xyz' . rand(100, 1000), |
||
482 | $storeTransfer, |
||
483 | ); |
||
484 | |||
485 | // Assert |
||
486 | $this->assertNull($productAbstractAvailabilityTransfer); |
||
487 | } |
||
488 | |||
489 | /** |
||
490 | * @return void |
||
491 | */ |
||
492 | public function testFindProductAbstractAvailabilityForStoreWithStockAndNoCachedAvailability(): void |
||
493 | { |
||
494 | // Arrange |
||
495 | $abstractSku = 'testFindProductAbstractAvailabilityForStoreAbstract'; |
||
496 | $concreteSku1 = 'testFindProductAbstractAvailabilityForStore1'; |
||
497 | $concreteSku2 = 'testFindProductAbstractAvailabilityForStore2'; |
||
498 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
499 | $productQuantity1 = rand(1, 10); |
||
500 | $productQuantity2 = rand(1, 10); |
||
501 | $this->createProductWithStock( |
||
502 | $abstractSku, |
||
503 | $concreteSku1, |
||
504 | ['quantity' => $productQuantity1], |
||
505 | $storeTransfer, |
||
506 | ); |
||
507 | |||
508 | $this->createProductWithStock( |
||
509 | $abstractSku, |
||
510 | $concreteSku2, |
||
511 | ['quantity' => $productQuantity2], |
||
512 | $storeTransfer, |
||
513 | ); |
||
514 | |||
515 | // Act |
||
516 | $productAbstractAvailabilityTransfer = $this->getAvailabilityFacade() |
||
517 | ->findOrCreateProductAbstractAvailabilityBySkuForStore( |
||
518 | $abstractSku, |
||
519 | $storeTransfer, |
||
520 | ); |
||
521 | |||
522 | // Assert |
||
523 | $this->assertNotNull($productAbstractAvailabilityTransfer); |
||
524 | $this->assertSame( |
||
525 | $productAbstractAvailabilityTransfer->getAvailability()->trim()->toInt(), |
||
526 | ($productQuantity1 + $productQuantity2), |
||
527 | ); |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * @return void |
||
532 | */ |
||
533 | public function testFindProductConcreteAvailabilityBySkuForStoreWithCachedAvailability(): void |
||
534 | { |
||
535 | // Arrange |
||
536 | $productQuantity = 6; |
||
537 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
538 | $productTransfer = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU], ['sku' => static::ABSTRACT_SKU]); |
||
539 | $this->tester->haveAvailabilityConcrete($productTransfer->getSku(), $storeTransfer, new Decimal($productQuantity)); |
||
540 | |||
541 | // Act |
||
542 | $productConcreteAvailabilityTransfer = $this->getAvailabilityFacade() |
||
543 | ->findOrCreateProductConcreteAvailabilityBySkuForStore( |
||
544 | $productTransfer->getSku(), |
||
545 | $storeTransfer, |
||
546 | ); |
||
547 | |||
548 | // Assert |
||
549 | $this->assertNotNull($productConcreteAvailabilityTransfer); |
||
550 | $this->assertSame($productQuantity, $productConcreteAvailabilityTransfer->getAvailability()->trim()->toInt()); |
||
551 | } |
||
552 | |||
553 | /** |
||
554 | * @return void |
||
555 | */ |
||
556 | public function testFindProductConcreteAvailabilityBySkuForStoreWithStockAndNoCachedAvailability(): void |
||
557 | { |
||
558 | // Arrange |
||
559 | $productQuantity = 13; |
||
560 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
561 | $stockProductEntity = $this->createProductWithStock( |
||
562 | static::ABSTRACT_SKU, |
||
563 | static::CONCRETE_SKU, |
||
564 | ['quantity' => $productQuantity], |
||
565 | $storeTransfer, |
||
566 | ); |
||
567 | |||
568 | // Act |
||
569 | $productConcreteAvailabilityTransfer = $this->getAvailabilityFacade() |
||
570 | ->findOrCreateProductConcreteAvailabilityBySkuForStore( |
||
571 | static::CONCRETE_SKU, |
||
572 | $storeTransfer, |
||
573 | ); |
||
574 | |||
575 | // Assert |
||
576 | $this->assertNotNull($productConcreteAvailabilityTransfer); |
||
577 | $this->assertSame($productQuantity, $productConcreteAvailabilityTransfer->getAvailability()->trim()->toInt()); |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * @return void |
||
582 | */ |
||
583 | public function testFindProductConcreteAvailabilityBySkuForStoreWithInvalidSku(): void |
||
584 | { |
||
585 | // Arrange |
||
586 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
587 | |||
588 | // Act |
||
589 | $productConcreteAvailabilityTransfer = $this->getAvailabilityFacade() |
||
590 | ->findOrCreateProductConcreteAvailabilityBySkuForStore( |
||
591 | 'xyz' . rand(100, 1000), |
||
592 | $storeTransfer, |
||
593 | ); |
||
594 | |||
595 | // Assert |
||
596 | $this->assertNull($productConcreteAvailabilityTransfer); |
||
597 | } |
||
598 | |||
599 | /** |
||
600 | * @return void |
||
601 | */ |
||
602 | public function testSaveProductAvailabilityForStoreShouldStoreAvailability(): void |
||
603 | { |
||
604 | // Arrange |
||
605 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
606 | $this->createProductWithStock( |
||
607 | static::ABSTRACT_SKU, |
||
608 | static::CONCRETE_SKU, |
||
609 | ['quantity' => 0], |
||
610 | $storeTransfer, |
||
611 | ); |
||
612 | |||
613 | // Act |
||
614 | $this->getAvailabilityFacade() |
||
615 | ->saveProductAvailabilityForStore(static::CONCRETE_SKU, new Decimal(2), $storeTransfer); |
||
616 | |||
617 | // Assert |
||
618 | $productConcreteAvailabilityTransfer = $this->getAvailabilityFacade() |
||
619 | ->findOrCreateProductConcreteAvailabilityBySkuForStore( |
||
620 | static::CONCRETE_SKU, |
||
621 | $storeTransfer, |
||
622 | ); |
||
623 | |||
624 | $this->assertTrue($productConcreteAvailabilityTransfer->getAvailability()->equals(2)); |
||
625 | } |
||
626 | |||
627 | /** |
||
628 | * @return void |
||
629 | */ |
||
630 | public function testIsProductConcreteAvailable(): void |
||
631 | { |
||
632 | if ($this->tester->isDynamicStoreEnabled()) { |
||
633 | $this->markTestSkipped('Deprecated code is not used with Dynamic Store'); |
||
634 | } |
||
635 | |||
636 | // Arrange |
||
637 | $productConcreteTransfer = $this->tester->haveProduct(); |
||
638 | $productConcreteTransfer2 = $this->tester->haveProduct(); |
||
639 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
640 | |||
641 | $this->getAvailabilityFacade()->saveProductAvailabilityForStore( |
||
642 | $productConcreteTransfer->getSku(), |
||
643 | new Decimal('1.1'), |
||
644 | $storeTransfer, |
||
645 | ); |
||
646 | |||
647 | // Act |
||
648 | $productAvailable = $this->getAvailabilityFacade() |
||
649 | ->isProductConcreteAvailable($productConcreteTransfer->getIdProductConcrete()); |
||
650 | |||
651 | $productAvailable2 = $this->getAvailabilityFacade() |
||
652 | ->isProductConcreteAvailable($productConcreteTransfer2->getIdProductConcrete()); |
||
653 | |||
654 | // Assert |
||
655 | $this->assertTrue($productAvailable); |
||
656 | $this->assertFalse($productAvailable2); |
||
657 | } |
||
658 | |||
659 | /** |
||
660 | * @return void |
||
661 | */ |
||
662 | public function testFilterAvailableProductsWithNeverOutOfStock(): void |
||
663 | { |
||
664 | // Arrange |
||
665 | $productConcreteTransfer = $this->tester->haveProduct([ProductConcreteTransfer::SKU => static::CONCRETE_SKU]); |
||
666 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
667 | $this->createProductWithStock( |
||
668 | static::ABSTRACT_SKU, |
||
669 | static::CONCRETE_SKU, |
||
670 | ['is_never_out_of_stock' => true], |
||
671 | $storeTransfer, |
||
672 | ); |
||
673 | if ($this->tester->isDynamicStoreEnabled()) { |
||
674 | $productConcreteTransfer->addStores($storeTransfer); |
||
675 | } |
||
676 | |||
677 | // Act |
||
678 | $productConcreteTransfers = $this->getAvailabilityFacade() |
||
679 | ->filterAvailableProducts([$productConcreteTransfer]); |
||
680 | |||
681 | // Assert |
||
682 | $this->assertCount(1, $productConcreteTransfers); |
||
683 | } |
||
684 | |||
685 | /** |
||
686 | * @return void |
||
687 | */ |
||
688 | public function testFilterAvailableProductsWithQuantity(): void |
||
689 | { |
||
690 | // Arrange |
||
691 | $productConcreteTransfer = $this->tester->haveProduct([ProductConcreteTransfer::SKU => static::CONCRETE_SKU]); |
||
692 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
693 | $this->createProductWithStock( |
||
694 | static::ABSTRACT_SKU, |
||
695 | static::CONCRETE_SKU, |
||
696 | ['quantity' => 2], |
||
697 | $storeTransfer, |
||
698 | ); |
||
699 | if ($this->tester->isDynamicStoreEnabled()) { |
||
700 | $productConcreteTransfer->addStores($storeTransfer); |
||
701 | } |
||
702 | |||
703 | // Act |
||
704 | $productConcreteTransfers = $this->getAvailabilityFacade() |
||
705 | ->filterAvailableProducts([$productConcreteTransfer]); |
||
706 | |||
707 | // Assert |
||
708 | $this->assertCount(1, $productConcreteTransfers); |
||
709 | } |
||
710 | |||
711 | /** |
||
712 | * @return void |
||
713 | */ |
||
714 | public function testFilterAvailableProductsWithZeroQuantity(): void |
||
715 | { |
||
716 | // Arrange |
||
717 | $productConcreteTransfer = $this->tester->haveProduct([ProductConcreteTransfer::SKU => static::CONCRETE_SKU]); |
||
718 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
719 | $this->createProductWithStock( |
||
720 | static::ABSTRACT_SKU, |
||
721 | static::CONCRETE_SKU, |
||
722 | ['quantity' => 0], |
||
723 | $storeTransfer, |
||
724 | ); |
||
725 | if ($this->tester->isDynamicStoreEnabled()) { |
||
726 | $productConcreteTransfer->addStores($storeTransfer); |
||
727 | } |
||
728 | |||
729 | // Act |
||
730 | $productConcreteTransfers = $this->getAvailabilityFacade() |
||
731 | ->filterAvailableProducts([$productConcreteTransfer]); |
||
732 | |||
733 | // Assert |
||
734 | $this->assertCount(0, $productConcreteTransfers); |
||
735 | } |
||
736 | |||
737 | /** |
||
738 | * @return void |
||
739 | */ |
||
740 | public function testFilterAvailableProductsWithoutStock(): void |
||
741 | { |
||
742 | // Arrange |
||
743 | $productConcreteTransfer = $this->tester->haveProduct([ProductConcreteTransfer::SKU => static::CONCRETE_SKU]); |
||
744 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
745 | if ($this->tester->isDynamicStoreEnabled()) { |
||
746 | $productConcreteTransfer->addStores($storeTransfer); |
||
747 | } |
||
748 | |||
749 | // Act |
||
750 | $productConcreteTransfers = $this->getAvailabilityFacade() |
||
751 | ->filterAvailableProducts([$productConcreteTransfer]); |
||
752 | |||
753 | // Assert |
||
754 | $this->assertCount(0, $productConcreteTransfers); |
||
755 | } |
||
756 | |||
757 | /** |
||
758 | * @return void |
||
759 | */ |
||
760 | public function testFilterAvailableProductsWithSeveralItems(): void |
||
761 | { |
||
762 | // Arrange |
||
763 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
764 | |||
765 | $firstProductConcreteTransfer = $this->tester->haveProduct(); |
||
766 | $this->createProductWithStock( |
||
767 | $firstProductConcreteTransfer->getAbstractSku(), |
||
768 | $firstProductConcreteTransfer->getSku(), |
||
769 | ['quantity' => 0], |
||
770 | $storeTransfer, |
||
771 | ); |
||
772 | |||
773 | $secondProductConcreteTransfer = $this->tester->haveProduct(); |
||
774 | $this->createProductWithStock( |
||
775 | $firstProductConcreteTransfer->getAbstractSku(), |
||
776 | $firstProductConcreteTransfer->getSku(), |
||
777 | ['quantity' => 2], |
||
778 | $storeTransfer, |
||
779 | ); |
||
780 | if ($this->tester->isDynamicStoreEnabled()) { |
||
781 | $firstProductConcreteTransfer->addStores($storeTransfer); |
||
782 | $secondProductConcreteTransfer->addStores($storeTransfer); |
||
783 | } |
||
784 | |||
785 | // Act |
||
786 | $productConcreteTransfers = $this->getAvailabilityFacade() |
||
787 | ->filterAvailableProducts([$firstProductConcreteTransfer, $secondProductConcreteTransfer]); |
||
788 | |||
789 | // Assert |
||
790 | $this->assertCount(1, $productConcreteTransfers); |
||
791 | } |
||
792 | |||
793 | /** |
||
794 | * @return void |
||
795 | */ |
||
796 | public function testGetProductConcreteAvailabilityCollectionReturnsAllAvailabilitiesWithNoCriteria(): void |
||
797 | { |
||
798 | // Arrange |
||
799 | $this->tester->ensureAvailabilityTableIsEmpty(); |
||
800 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
801 | $productTransfer1 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU]); |
||
802 | $productTransfer2 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU . 1]); |
||
803 | $productTransfer3 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU . 2]); |
||
804 | $this->tester->haveAvailabilityConcrete($productTransfer1->getSku(), $storeTransfer, new Decimal(1)); |
||
805 | $this->tester->haveAvailabilityConcrete($productTransfer2->getSku(), $storeTransfer, new Decimal(2)); |
||
806 | $this->tester->haveAvailabilityConcrete($productTransfer3->getSku(), $storeTransfer, new Decimal(3)); |
||
807 | |||
808 | // Act |
||
809 | $productConcreteAvailabilityCollectionTransfer = $this->getAvailabilityFacade()->getProductConcreteAvailabilityCollection( |
||
810 | new ProductAvailabilityCriteriaTransfer(), |
||
811 | ); |
||
812 | |||
813 | // Assert |
||
814 | $this->assertCount(3, $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()); |
||
815 | } |
||
816 | |||
817 | /** |
||
818 | * @return void |
||
819 | */ |
||
820 | public function testGetProductConcreteAvailabilityCollectionReturnsAvailabilitiesFilteredBySkus(): void |
||
821 | { |
||
822 | // Arrange |
||
823 | $this->tester->ensureAvailabilityTableIsEmpty(); |
||
824 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
825 | $productTransfer1 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU]); |
||
826 | $productTransfer2 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU . 1]); |
||
827 | $this->tester->haveAvailabilityConcrete($productTransfer1->getSku(), $storeTransfer, new Decimal(1)); |
||
828 | $this->tester->haveAvailabilityConcrete($productTransfer2->getSku(), $storeTransfer, new Decimal(2)); |
||
829 | |||
830 | // Act |
||
831 | $productConcreteAvailabilityCollectionTransfer = $this->getAvailabilityFacade()->getProductConcreteAvailabilityCollection( |
||
832 | (new ProductAvailabilityCriteriaTransfer())->addProductConcreteSku($productTransfer2->getSku()), |
||
833 | ); |
||
834 | |||
835 | // Assert |
||
836 | $this->assertCount(1, $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()); |
||
837 | $this->assertSame( |
||
838 | $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()[0]->getSku(), |
||
839 | $productTransfer2->getSku(), |
||
840 | ); |
||
841 | $this->assertSame( |
||
842 | $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()[0]->getAvailability()->toInt(), |
||
843 | 2, |
||
844 | ); |
||
845 | } |
||
846 | |||
847 | /** |
||
848 | * @return void |
||
849 | */ |
||
850 | public function testGetProductConcreteAvailabilityCollectionReturnsAvailabilitiesFilteredByStoreIds(): void |
||
851 | { |
||
852 | // Arrange |
||
853 | $this->tester->ensureAvailabilityTableIsEmpty(); |
||
854 | $storeTransfer1 = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE], false); |
||
855 | $storeTransfer2 = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_AT], false); |
||
856 | $productTransfer1 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU]); |
||
857 | $productTransfer2 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU . 1]); |
||
858 | $this->tester->haveAvailabilityConcrete($productTransfer1->getSku(), $storeTransfer1, new Decimal(1)); |
||
859 | $this->tester->haveAvailabilityConcrete($productTransfer2->getSku(), $storeTransfer2, new Decimal(2)); |
||
860 | |||
861 | // Act |
||
862 | $productConcreteAvailabilityCollectionTransfer = $this->getAvailabilityFacade()->getProductConcreteAvailabilityCollection( |
||
863 | (new ProductAvailabilityCriteriaTransfer())->addIdStore($storeTransfer1->getIdStore()), |
||
864 | ); |
||
865 | |||
866 | // Assert |
||
867 | $this->assertCount(1, $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()); |
||
868 | $this->assertSame( |
||
869 | $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()[0]->getSku(), |
||
870 | $productTransfer1->getSku(), |
||
871 | ); |
||
872 | $this->assertSame( |
||
873 | $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()[0]->getAvailability()->toInt(), |
||
874 | 1, |
||
875 | ); |
||
876 | } |
||
877 | |||
878 | /** |
||
879 | * @return void |
||
880 | */ |
||
881 | public function testGetProductConcreteAvailabilityCollectionReturnsNoAvailabilitiesIfNoAvailabilitiesMeetCriteria(): void |
||
882 | { |
||
883 | // Arrange |
||
884 | $this->tester->ensureAvailabilityTableIsEmpty(); |
||
885 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
886 | $productTransfer1 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU]); |
||
887 | $productTransfer2 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU . 1]); |
||
888 | $this->tester->haveAvailabilityConcrete($productTransfer1->getSku(), $storeTransfer, new Decimal(1)); |
||
889 | $this->tester->haveAvailabilityConcrete($productTransfer2->getSku(), $storeTransfer, new Decimal(2)); |
||
890 | |||
891 | // Act |
||
892 | $productConcreteAvailabilityCollectionTransfer = $this->getAvailabilityFacade()->getProductConcreteAvailabilityCollection( |
||
893 | (new ProductAvailabilityCriteriaTransfer()) |
||
894 | ->addIdStore($storeTransfer->getIdStore() + 1) |
||
895 | ->addProductConcreteSku(static::CONCRETE_SKU . 2), |
||
896 | ); |
||
897 | |||
898 | // Assert |
||
899 | $this->assertCount(0, $productConcreteAvailabilityCollectionTransfer->getProductConcreteAvailabilities()); |
||
900 | } |
||
901 | |||
902 | /** |
||
903 | * @return void |
||
904 | */ |
||
905 | public function testExpandWishlistItemWithAvailabilitySuccess(): void |
||
906 | { |
||
907 | // Arrange |
||
908 | $this->tester->ensureAvailabilityTableIsEmpty(); |
||
909 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
910 | $productTransfer1 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU]); |
||
911 | $wishlsitItemTransfer = (new WishlistItemTransfer())->setSku($productTransfer1->getSku()); |
||
912 | $productConcreteAvailabilityTransfer = $this->tester->haveAvailabilityConcrete($productTransfer1->getSku(), $storeTransfer, new Decimal(1)); |
||
913 | |||
914 | /** |
||
915 | * @see \Spryker\Zed\Wishlist\Business\WishlistFacade is used via GatewayController, so there is a current store in context of this plugin usage. |
||
916 | */ |
||
917 | $this->tester->addCurrentStore($storeTransfer); |
||
918 | |||
919 | // Act |
||
920 | $wishlsitItemTransfer = $this->tester->getFacade()->expandWishlistItemWithAvailability($wishlsitItemTransfer); |
||
921 | |||
922 | // Assert |
||
923 | $this->assertSame($wishlsitItemTransfer->getProductConcreteAvailability()->getSku(), $productConcreteAvailabilityTransfer->getSku()); |
||
924 | $this->assertSame($wishlsitItemTransfer->getProductConcreteAvailability()->getIsNeverOutOfStock(), $productConcreteAvailabilityTransfer->getIsNeverOutOfStock()); |
||
925 | } |
||
926 | |||
927 | /** |
||
928 | * @return void |
||
929 | */ |
||
930 | public function testExpandWishlistItemWithSellableSuccess(): void |
||
931 | { |
||
932 | // Arrange |
||
933 | $this->tester->ensureAvailabilityTableIsEmpty(); |
||
934 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
935 | $productTransfer1 = $this->tester->haveProduct(['sku' => static::CONCRETE_SKU]); |
||
936 | $wishlsitItemTransfer = (new WishlistItemTransfer())->setSku($productTransfer1->getSku()); |
||
937 | $productConcreteAvailabilityTransfer = $this->tester->haveAvailabilityConcrete($productTransfer1->getSku(), $storeTransfer, new Decimal(1)); |
||
0 ignored issues
–
show
Unused Code
introduced
by
Loading history...
|
|||
938 | |||
939 | /** |
||
940 | * @see \Spryker\Zed\Wishlist\Business\WishlistFacade is used via GatewayController, so there is a current store in context of this plugin usage. |
||
941 | */ |
||
942 | $this->tester->addCurrentStore($storeTransfer); |
||
943 | |||
944 | // Act |
||
945 | $wishlsitItemTransfer = $this->tester->getFacade()->expandWishlistItemWithSellable($wishlsitItemTransfer); |
||
946 | |||
947 | // Assert |
||
948 | $this->assertTrue($wishlsitItemTransfer->getIsSellable()); |
||
949 | } |
||
950 | |||
951 | /** |
||
952 | * @return void |
||
953 | */ |
||
954 | public function testUpdateAvailabilityByDynamicEntityRequestDoesNotUpdateAvailabilityForWrongTableName(): void |
||
955 | { |
||
956 | // Arrange |
||
957 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
958 | $stockProductEntity = $this->createProductWithStock( |
||
959 | static::ABSTRACT_SKU, |
||
960 | static::CONCRETE_SKU, |
||
961 | ['quantity' => 5], |
||
962 | $storeTransfer, |
||
963 | ); |
||
964 | |||
965 | $stockProductEntity->setQuantity(50); |
||
966 | $stockProductEntity->save(); |
||
967 | |||
968 | $dynamicEntityPostEditRequestTransfer = new DynamicEntityPostEditRequestTransfer(); |
||
969 | $dynamicEntityPostEditRequestTransfer->setTableName(static::TEST_TABLE_NAME); |
||
970 | $dynamicEntityPostEditRequestTransfer->addRawDynamicEntity( |
||
971 | (new RawDynamicEntityTransfer())->setFields([static::FK_PRODUCT => $stockProductEntity->getFkProduct()]), |
||
972 | ); |
||
973 | |||
974 | // Act |
||
975 | $this->getAvailabilityFacade()->updateAvailabilityByDynamicEntityRequest($dynamicEntityPostEditRequestTransfer); |
||
976 | |||
977 | // Assert |
||
978 | $availabilityEntity = $this->tester->getAvailabilityQuery()->findOneBySku(static::CONCRETE_SKU); |
||
979 | $this->assertNotNull($availabilityEntity); |
||
980 | $this->assertSame(5, (new Decimal($availabilityEntity->getQuantity()))->toInt()); |
||
981 | |||
982 | $availabilityAbstractEntity = $this->tester->getAvailabilityAbstractQuery()->findOneByAbstractSku(static::ABSTRACT_SKU); |
||
983 | $this->assertNotNull($availabilityAbstractEntity); |
||
984 | $this->assertSame(5, (new Decimal($availabilityAbstractEntity->getQuantity()))->toInt()); |
||
985 | } |
||
986 | |||
987 | /** |
||
988 | * @return void |
||
989 | */ |
||
990 | public function testUpdateAvailabilityByDynamicEntityRequestUpdatesAvailabilityForValidTableName(): void |
||
991 | { |
||
992 | // Arrange |
||
993 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
994 | $stockProductEntity = $this->createProductWithStock( |
||
995 | static::ABSTRACT_SKU, |
||
996 | static::CONCRETE_SKU, |
||
997 | ['quantity' => 5], |
||
998 | $storeTransfer, |
||
999 | ); |
||
1000 | |||
1001 | $stockProductEntity->setQuantity(50); |
||
1002 | $stockProductEntity->save(); |
||
1003 | |||
1004 | $dynamicEntityPostEditRequestTransfer = new DynamicEntityPostEditRequestTransfer(); |
||
1005 | $dynamicEntityPostEditRequestTransfer->setTableName(static::STOCK_PRODUCT_TABLE_NAME); |
||
1006 | $dynamicEntityPostEditRequestTransfer->addRawDynamicEntity( |
||
1007 | (new RawDynamicEntityTransfer())->setFields([static::FK_PRODUCT => $stockProductEntity->getFkProduct()]), |
||
1008 | ); |
||
1009 | |||
1010 | // Act |
||
1011 | $this->getAvailabilityFacade()->updateAvailabilityByDynamicEntityRequest($dynamicEntityPostEditRequestTransfer); |
||
1012 | |||
1013 | // Assert |
||
1014 | $availabilityEntity = $this->tester->getAvailabilityQuery()->findOneBySku(static::CONCRETE_SKU); |
||
1015 | $this->assertNotNull($availabilityEntity); |
||
1016 | $this->assertSame(50, (new Decimal($availabilityEntity->getQuantity()))->toInt()); |
||
1017 | |||
1018 | $availabilityAbstractEntity = $this->tester->getAvailabilityAbstractQuery()->findOneByAbstractSku(static::ABSTRACT_SKU); |
||
1019 | $this->assertNotNull($availabilityAbstractEntity); |
||
1020 | $this->assertSame(50, (new Decimal($availabilityAbstractEntity->getQuantity()))->toInt()); |
||
1021 | } |
||
1022 | |||
1023 | /** |
||
1024 | * @return \Spryker\Zed\Availability\Business\AvailabilityFacade |
||
1025 | */ |
||
1026 | protected function getAvailabilityFacade(): AvailabilityFacade |
||
1027 | { |
||
1028 | /** @var \Spryker\Zed\Availability\Business\AvailabilityFacade $availabilityFacade */ |
||
1029 | $availabilityFacade = $this->tester->getFacade(); |
||
1030 | |||
1031 | $container = new Container(); |
||
1032 | $container->set(AvailabilityDependencyProvider::FACADE_STOCK, function () { |
||
1033 | return $this->createStockFacadeMock(); |
||
1034 | }); |
||
1035 | $availabilityBusinessFactory = new AvailabilityBusinessFactory(); |
||
1036 | $dependencyProvider = new AvailabilityDependencyProvider(); |
||
1037 | $dependencyProvider->provideBusinessLayerDependencies($container); |
||
1038 | $availabilityBusinessFactory->setContainer($container); |
||
1039 | $availabilityFacade->setFactory($availabilityBusinessFactory); |
||
1040 | |||
1041 | return $availabilityFacade; |
||
1042 | } |
||
1043 | |||
1044 | /** |
||
1045 | * @param string $abstractSku |
||
1046 | * @param string $concreteSku |
||
1047 | * @param array $stockData |
||
1048 | * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer |
||
1049 | * |
||
1050 | * @return \Orm\Zed\Stock\Persistence\SpyStockProduct |
||
1051 | */ |
||
1052 | protected function createProductWithStock( |
||
1053 | string $abstractSku, |
||
1054 | string $concreteSku, |
||
1055 | array $stockData, |
||
1056 | StoreTransfer $storeTransfer |
||
1057 | ): SpyStockProduct { |
||
1058 | $productAbstractEntity = (new SpyProductAbstractQuery()) |
||
1059 | ->filterBySku($abstractSku) |
||
1060 | ->findOneOrCreate(); |
||
1061 | $productAbstractEntity->setAttributes(''); |
||
1062 | $productAbstractEntity->save(); |
||
1063 | |||
1064 | $productEntity = (new SpyProductQuery()) |
||
1065 | ->filterBySku($concreteSku) |
||
1066 | ->findOneOrCreate(); |
||
1067 | |||
1068 | $productEntity->setAttributes(''); |
||
1069 | $productEntity->setIsActive(true); |
||
1070 | $productEntity->setFkProductAbstract($productAbstractEntity->getIdProductAbstract()); |
||
1071 | $productEntity->save(); |
||
1072 | |||
1073 | $stockEntity = (new SpyStockQuery()) |
||
1074 | ->filterByName('Warehouse1') |
||
1075 | ->findOneOrCreate(); |
||
1076 | |||
1077 | $stockEntity->save(); |
||
1078 | |||
1079 | $stockProductEntity = (new SpyStockProductQuery()) |
||
1080 | ->filterByFkProduct($productEntity->getIdProduct()) |
||
1081 | ->filterByFkStock($stockEntity->getIdStock()) |
||
1082 | ->findOneOrCreate(); |
||
1083 | |||
1084 | $stockProductEntity->fromArray($stockData); |
||
1085 | $stockProductEntity->save(); |
||
1086 | |||
1087 | $this->getAvailabilityFacade()->updateAvailabilityForStore($concreteSku, $storeTransfer); |
||
1088 | |||
1089 | return $stockProductEntity; |
||
1090 | } |
||
1091 | |||
1092 | /** |
||
1093 | * @return \Generated\Shared\Transfer\QuoteTransfer |
||
1094 | */ |
||
1095 | protected function createQuoteTransfer(): QuoteTransfer |
||
1096 | { |
||
1097 | $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]); |
||
1098 | $quoteTransfer = new QuoteTransfer(); |
||
1099 | $quoteTransfer->setStore($storeTransfer); |
||
1100 | $itemTransfer = new ItemTransfer(); |
||
1101 | $itemTransfer->setSku(static::CONCRETE_SKU); |
||
1102 | $itemTransfer->setQuantity(1); |
||
1103 | $quoteTransfer->addItem($itemTransfer); |
||
1104 | |||
1105 | return $quoteTransfer; |
||
1106 | } |
||
1107 | |||
1108 | /** |
||
1109 | * @param string $abstractSku |
||
1110 | * @param string $concreteSku |
||
1111 | * @param \Spryker\DecimalObject\Decimal $quantity |
||
1112 | * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer |
||
1113 | * |
||
1114 | * @return \Orm\Zed\Availability\Persistence\SpyAvailability |
||
1115 | */ |
||
1116 | protected function createProductAvailability( |
||
1117 | string $abstractSku, |
||
1118 | string $concreteSku, |
||
1119 | Decimal $quantity, |
||
1120 | StoreTransfer $storeTransfer |
||
1121 | ): SpyAvailability { |
||
1122 | $availabilityAbstractEntity = (new SpyAvailabilityAbstractQuery()) |
||
1123 | ->filterByAbstractSku($abstractSku) |
||
1124 | ->filterByFkStore($storeTransfer->getIdStore()) |
||
1125 | ->findOneOrCreate(); |
||
1126 | |||
1127 | $availabilityAbstractEntity->setQuantity($quantity)->save(); |
||
1128 | |||
1129 | $availabilityEntity = (new SpyAvailabilityQuery()) |
||
1130 | ->filterByFkAvailabilityAbstract($availabilityAbstractEntity->getIdAvailabilityAbstract()) |
||
1131 | ->filterByFkStore($storeTransfer->getIdStore()) |
||
1132 | ->filterBySku($concreteSku) |
||
1133 | ->findOneOrCreate(); |
||
1134 | |||
1135 | $availabilityEntity->setQuantity($quantity)->save(); |
||
1136 | |||
1137 | return $availabilityEntity; |
||
1138 | } |
||
1139 | |||
1140 | /** |
||
1141 | * @return \PHPUnit\Framework\MockObject\MockObject|\Spryker\Zed\Availability\Dependency\Facade\AvailabilityToStockFacadeInterface |
||
1142 | */ |
||
1143 | protected function createStockFacadeMock(): AvailabilityToStockFacadeInterface |
||
1144 | { |
||
1145 | $mock = $this->getMockBuilder(AvailabilityToStockFacadeInterface::class)->getMock(); |
||
1146 | $mock->method('getStoreToWarehouseMapping') |
||
1147 | ->willReturn([static::STORE_NAME_DE => ['Warehouse1']]); |
||
1148 | $mock->method('getStoresWhereProductStockIsDefined') |
||
1149 | ->willReturn((new StoreTransfer())->setName(static::STORE_NAME_DE)); |
||
1150 | |||
1151 | return $mock; |
||
1152 | } |
||
1153 | } |
||
1154 |