Issues (3641)

Availability/Business/AvailabilityFacadeTest.php (1 issue)

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
The assignment to $productConcreteAvailabilityTransfer is dead and can be removed.
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