Failed Conditions
Push — master ( 999028...ace778 )
by
unknown
37:54
created

testUpdateStockShouldRemoveStoreRelations()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 15
rs 10
c 0
b 0
f 0
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\Stock\Business;
9
10
use ArrayObject;
11
use Codeception\Test\Unit;
12
use Generated\Shared\DataBuilder\StockBuilder;
13
use Generated\Shared\Transfer\ProductConcreteTransfer;
14
use Generated\Shared\Transfer\StockCriteriaFilterTransfer;
15
use Generated\Shared\Transfer\StockProductTransfer;
16
use Generated\Shared\Transfer\StockStoreCriteriaTransfer;
17
use Generated\Shared\Transfer\StockTransfer;
18
use Generated\Shared\Transfer\StoreRelationTransfer;
19
use Generated\Shared\Transfer\StoreTransfer;
20
use Generated\Shared\Transfer\TypeTransfer;
21
use Orm\Zed\Product\Persistence\SpyProduct;
22
use Orm\Zed\Product\Persistence\SpyProductAbstract;
23
use Orm\Zed\Stock\Persistence\SpyStock;
24
use Orm\Zed\Stock\Persistence\SpyStockProduct;
25
use Orm\Zed\Stock\Persistence\SpyStockProductQuery;
26
use Orm\Zed\Stock\Persistence\SpyStockQuery;
27
use Spryker\DecimalObject\Decimal;
28
use Spryker\Zed\Stock\Business\Exception\StockProductAlreadyExistsException;
29
use Spryker\Zed\Stock\Business\Stock\StockStoreRelationshipUpdaterInterface;
30
use Spryker\Zed\Stock\Business\Stock\StockUpdater;
31
use Spryker\Zed\Stock\Business\StockProduct\StockProductUpdaterInterface;
32
use Spryker\Zed\Stock\Dependency\Facade\StockToEventFacadeInterface;
33
use Spryker\Zed\Stock\Dependency\Facade\StockToTouchInterface;
34
use Spryker\Zed\Stock\Persistence\StockEntityManager;
35
use Spryker\Zed\Stock\Persistence\StockRepository;
36
37
/**
38
 * Auto-generated group annotations
39
 *
40
 * @group SprykerTest
41
 * @group Zed
42
 * @group Stock
43
 * @group Business
44
 * @group Facade
45
 * @group StockFacadeTest
46
 * Add your own group annotations below this line
47
 */
48
class StockFacadeTest extends Unit
49
{
50
    /**
51
     * @var string
52
     */
53
    protected const STORE_NAME_DE = 'DE';
54
55
    /**
56
     * @var string
57
     */
58
    protected const STORE_NAME_AT = 'AT';
59
60
    /**
61
     * @var string
62
     */
63
    protected const STORE_NAME_TEST_STORE = 'TEST_STORE';
64
65
    /**
66
     * @var string
67
     */
68
    protected const STOCK_NAME = 'Test Warehouse';
69
70
    /**
71
     * @var int
72
     */
73
    protected const INVALID_STOCK_ID = 0;
74
75
    /**
76
     * @var \SprykerTest\Zed\Stock\StockBusinessTester
77
     */
78
    protected $tester;
79
80
    /**
81
     * @var \Spryker\Zed\Stock\Business\StockFacade
82
     */
83
    protected $stockFacade;
84
85
    /**
86
     * @var \Generated\Shared\Transfer\StoreTransfer
87
     */
88
    protected $storeTransfer;
89
90
    /**
91
     * @var \Orm\Zed\Stock\Persistence\SpyStock
92
     */
93
    protected $stockEntity1;
94
95
    /**
96
     * @var \Generated\Shared\Transfer\StockTransfer
97
     */
98
    protected $stockTransfer1;
99
100
    /**
101
     * @var \Orm\Zed\Stock\Persistence\SpyStock
102
     */
103
    protected $stockEntity2;
104
105
    /**
106
     * @var \Generated\Shared\Transfer\StockTransfer
107
     */
108
    protected $stockTransfer2;
109
110
    /**
111
     * @var \Orm\Zed\Stock\Persistence\SpyStockProduct
112
     */
113
    protected $productStockEntity1;
114
115
    /**
116
     * @var \Orm\Zed\Stock\Persistence\SpyStockProduct
117
     */
118
    protected $productStockEntity2;
119
120
    /**
121
     * @var \Orm\Zed\Product\Persistence\SpyProductAbstract
122
     */
123
    protected $productAbstractEntity;
124
125
    /**
126
     * @var \Orm\Zed\Product\Persistence\SpyProduct
127
     */
128
    protected $productConcreteEntity;
129
130
    /**
131
     * @var string
132
     */
133
    public const ABSTRACT_SKU = 'abstract-sku';
134
135
    /**
136
     * @var string
137
     */
138
    public const CONCRETE_SKU = 'concrete-sku';
139
140
    /**
141
     * @var int
142
     */
143
    public const STOCK_QUANTITY_1 = 92;
144
145
    public const STOCK_QUANTITY_2 = 8.2;
146
147
    /**
148
     * @return void
149
     */
150
    public function setUp(): void
151
    {
152
        parent::setUp();
153
154
        $this->stockFacade = $this->tester->getFacade();
155
        $this->setupData();
156
    }
157
158
    /**
159
     * @return void
160
     */
161
    public function testIsNeverOutOfStockShouldReturnFalse(): void
162
    {
163
        $isNeverOutOfStock = $this->stockFacade->isNeverOutOfStock(static::CONCRETE_SKU);
164
165
        $this->assertFalse($isNeverOutOfStock);
166
    }
167
168
    /**
169
     * @return void
170
     */
171
    public function testIsNeverOutOfStockShouldReturnTrue(): void
172
    {
173
        $this->productStockEntity1->setIsNeverOutOfStock(true);
174
        $this->productStockEntity1->setQuantity(null);
175
        $this->productStockEntity1->save();
176
177
        $isNeverOutOfStock = $this->stockFacade->isNeverOutOfStock(static::CONCRETE_SKU);
178
179
        $this->assertTrue($isNeverOutOfStock);
180
    }
181
182
    /**
183
     * @return void
184
     */
185
    public function testIsProductAbstractNeverOutOfStockForStoreShouldReturnTrueWhenOneOfTheConcreteProductsIsNeverOutOfStock(): void
186
    {
187
        //Arrange
188
        $this->productStockEntity1->setIsNeverOutOfStock(true);
189
        $this->productStockEntity1->save();
190
191
        //Act
192
        $isNeverOutOfStock = $this->stockFacade->isProductAbstractNeverOutOfStockForStore(
193
            static::ABSTRACT_SKU,
194
            $this->storeTransfer,
195
        );
196
197
        //Assert
198
        $this->assertTrue($isNeverOutOfStock);
199
    }
200
201
    /**
202
     * @return void
203
     */
204
    public function testIsProductAbstractNeverOutOfStockForStoreShouldReturnFalseWhenNoneOfTheConcreteProductsIsNeverOutOfStock(): void
205
    {
206
        //Arrange
207
        $this->productStockEntity1->setIsNeverOutOfStock(false);
208
        $this->productStockEntity1->save();
209
210
        //Act
211
        $isNeverOutOfStock = $this->stockFacade->isProductAbstractNeverOutOfStockForStore(
212
            static::ABSTRACT_SKU,
213
            $this->storeTransfer,
214
        );
215
216
        //Assert
217
        $this->assertFalse($isNeverOutOfStock);
218
    }
219
220
    /**
221
     * @return void
222
     */
223
    public function testCalculateStockForProductShouldCheckAllStocks(): void
224
    {
225
        $productStock = $this->stockFacade->calculateStockForProduct(static::CONCRETE_SKU);
226
227
        $this->assertTrue($productStock->equals('100.2'));
228
    }
229
230
    /**
231
     * @return void
232
     */
233
    public function testCalculateProductAbstractStockForStoreWillCalculateStockOfAllConcreteProductsOfAbstractProduct(): void
234
    {
235
        //Act
236
        $productAbstractStock = $this->stockFacade->calculateProductAbstractStockForStore(
237
            static::ABSTRACT_SKU,
238
            $this->storeTransfer,
239
        );
240
241
        //Assert
242
        $this->assertTrue($productAbstractStock->equals(static::STOCK_QUANTITY_1));
243
    }
244
245
    /**
246
     * @return void
247
     */
248
    public function testCreateStockType(): void
249
    {
250
        $stockTypeTransfer = (new TypeTransfer())
251
            ->setName('Test-Stock-Type');
252
253
        $idStock = $this->stockFacade->createStockType($stockTypeTransfer);
254
255
        $exists = SpyStockQuery::create()
256
                ->filterByIdStock($idStock)
257
                ->count() > 0;
258
259
        $this->assertTrue($exists);
260
    }
261
262
    /**
263
     * @return void
264
     */
265
    public function testCreateStockProduct(): void
266
    {
267
        $productAbstractEntity = new SpyProductAbstract();
268
        $productAbstractEntity
269
            ->setSku('foo')
270
            ->setAttributes('{}')
271
            ->save();
272
273
        $productConcreteEntity = new SpyProduct();
274
        $productConcreteEntity
275
            ->setSku('foo')
276
            ->setAttributes('{}')
277
            ->setFkProductAbstract($this->productAbstractEntity->getIdProductAbstract())
278
            ->save();
279
280
        $stockProductTransfer = (new StockProductTransfer())
281
            ->setStockType($this->stockEntity1->getName())
282
            ->setQuantity(static::STOCK_QUANTITY_1)
283
            ->setSku('foo');
284
285
        $idStockProduct = $this->stockFacade->createStockProduct($stockProductTransfer);
286
287
        $stockProductEntity = SpyStockProductQuery::create()
288
            ->filterByIdStockProduct($idStockProduct)
289
            ->findOne();
290
291
        $this->assertSame('92.0000000000', $stockProductEntity->getQuantity());
292
    }
293
294
    /**
295
     * @return void
296
     */
297
    public function testCreateStockProductShouldThrowException(): void
298
    {
299
        // Arrange
300
        $stockProductTransfer = (new StockProductTransfer())
301
            ->setStockType($this->stockEntity1->getName())
302
            ->setQuantity(static::STOCK_QUANTITY_1)
303
            ->setSku(static::CONCRETE_SKU);
304
305
        // Assert
306
        $this->expectException(StockProductAlreadyExistsException::class);
307
        $this->expectExceptionMessage('Cannot duplicate entry: this stock type is already set for this product');
308
309
        // Act
310
        $this->stockFacade->createStockProduct($stockProductTransfer);
311
    }
312
313
    /**
314
     * @return void
315
     */
316
    public function testUpdateStockProduct(): void
317
    {
318
        $stockProductTransfer = (new StockProductTransfer())
319
            ->setIdStockProduct($this->productStockEntity1->getIdStockProduct())
320
            ->setStockType($this->stockEntity1->getName())
321
            ->setQuantity(555)
322
            ->setSku(static::CONCRETE_SKU);
323
324
        $idStockProduct = $this->stockFacade->updateStockProduct($stockProductTransfer);
325
326
        $stockProductEntity = SpyStockProductQuery::create()
327
            ->filterByIdStockProduct($idStockProduct)
328
            ->findOne();
329
330
        $this->assertSame('555.0000000000', $stockProductEntity->getQuantity());
331
    }
332
333
    /**
334
     * @return void
335
     */
336
    public function testDecrementStockShouldReduceStockSize(): void
337
    {
338
        $this->stockFacade->decrementStockProduct(
339
            static::CONCRETE_SKU,
340
            $this->stockEntity1->getName(),
341
            new Decimal(10),
342
        );
343
344
        $stockSize = $this->stockFacade->calculateStockForProduct(static::CONCRETE_SKU);
345
346
        $this->assertTrue($stockSize->equals('90.2'));
347
    }
348
349
    /**
350
     * @return void
351
     */
352
    public function testIncrementStockShouldIncreaseStockSize(): void
353
    {
354
        $this->stockFacade->incrementStockProduct(
355
            static::CONCRETE_SKU,
356
            $this->stockEntity1->getName(),
357
            new Decimal(10),
358
        );
359
360
        $stockSize = $this->stockFacade->calculateStockForProduct(static::CONCRETE_SKU);
361
362
        $this->assertTrue($stockSize->equals('110.2'));
363
    }
364
365
    /**
366
     * @return void
367
     */
368
    public function testHasStockProductShouldReturnTrue(): void
369
    {
370
        $exists = $this->stockFacade->hasStockProduct(
371
            static::CONCRETE_SKU,
372
            $this->stockEntity1->getName(),
373
        );
374
375
        $this->assertTrue($exists);
376
    }
377
378
    /**
379
     * @return void
380
     */
381
    public function testHasStockProductShouldReturnFalse(): void
382
    {
383
        $exists = $this->stockFacade->hasStockProduct(
384
            'INVALIDSKU',
385
            'INVALIDTYPE',
386
        );
387
388
        $this->assertFalse($exists);
389
    }
390
391
    /**
392
     * @return void
393
     */
394
    public function testPersistStockProductCollection(): void
395
    {
396
        $increment = 20;
397
398
        $stockTransfer1 = (new StockProductTransfer())
399
            ->setSku(static::CONCRETE_SKU)
400
            ->setQuantity(static::STOCK_QUANTITY_1 + $increment)
401
            ->setIsNeverOutOfStock(false)
402
            ->setStockType($this->stockEntity1->getName());
403
404
        $stockTransfer2 = (new StockProductTransfer())
405
            ->setSku(static::CONCRETE_SKU)
406
            ->setQuantity(static::STOCK_QUANTITY_1 + $increment)
407
            ->setIsNeverOutOfStock(false)
408
            ->setStockType($this->stockEntity2->getName());
409
410
        $productConcreteTransfer = (new ProductConcreteTransfer())
411
            ->setStocks(new ArrayObject([
412
                $stockTransfer1, $stockTransfer2,
413
            ]));
414
415
        $this->stockFacade->persistStockProductCollection($productConcreteTransfer);
416
417
        $stockProductEntityCollection = SpyStockProductQuery::create()
418
            ->joinStock()
419
            ->filterByFkProduct($this->productConcreteEntity->getIdProduct())
420
            ->find();
421
422
        $this->assertNotEmpty($stockProductEntityCollection);
423
424
        foreach ($stockProductEntityCollection as $stockProductEntity) {
425
            // static::STOCK_QUANTITY_1 + $increment
426
            $this->assertSame('112.0000000000', $stockProductEntity->getQuantity());
427
            $this->assertSame($this->productConcreteEntity->getIdProduct(), $stockProductEntity->getFkProduct());
428
        }
429
    }
430
431
    /**
432
     * @return void
433
     */
434
    public function testExpandProductConcreteWithStocks(): void
435
    {
436
        $productConcreteTransfer = (new ProductConcreteTransfer())
437
            ->setIdProductConcrete($this->productConcreteEntity->getIdProduct())
438
            ->setSku(static::CONCRETE_SKU);
439
440
        $productConcreteTransfer = $this->stockFacade->expandProductConcreteWithStocks($productConcreteTransfer);
441
442
        $this->assertNotEmpty($productConcreteTransfer->getStocks());
443
        foreach ($productConcreteTransfer->getStocks() as $stock) {
444
            $this->assertTrue($stock->getQuantity()->greaterThan(0));
445
            $this->assertSame($stock->getSku(), static::CONCRETE_SKU);
446
        }
447
    }
448
449
    /**
450
     * @return void
451
     */
452
    public function testExpandProductConcreteTransfersWithStocksSuccessful(): void
453
    {
454
        // Arrange
455
        $productConcreteTransfer = (new ProductConcreteTransfer())
456
            ->setIdProductConcrete($this->productConcreteEntity->getIdProduct())
457
            ->setSku(static::CONCRETE_SKU);
458
459
        $productConcreteTransfer2 = (new ProductConcreteTransfer())
460
            ->setIdProductConcrete($this->productAbstractEntity->getIdProductAbstract())
461
            ->setSku('unknown');
462
463
        // Act
464
        $productConcreteTransfers = $this->stockFacade->expandProductConcreteTransfersWithStocks([$productConcreteTransfer, $productConcreteTransfer2]);
465
466
        // Assert
467
        $this->assertNotEmpty($productConcreteTransfers[0]->getStocks());
468
        foreach ($productConcreteTransfers[0]->getStocks() as $stock) {
469
            $this->assertTrue($stock->getQuantity()->greaterThan(0));
470
            $this->assertSame($stock->getSku(), static::CONCRETE_SKU);
471
        }
472
473
        $this->assertEmpty($productConcreteTransfers[1]->getStocks());
474
    }
475
476
    /**
477
     * @return void
478
     */
479
    public function testExpandProductConcreteWithStocksWillExpandOnlyWithActiveStocks(): void
480
    {
481
        //Arrange
482
        $this->stockEntity2->setIsActive(false)->save();
483
        $productConcreteTransfer = (new ProductConcreteTransfer())
484
            ->setIdProductConcrete($this->productConcreteEntity->getIdProduct())
485
            ->setSku(static::CONCRETE_SKU);
486
487
        //Act
488
        $productConcreteTransfer = $this->stockFacade->expandProductConcreteWithStocks($productConcreteTransfer);
489
490
        //Assert
491
        $this->assertNotEmpty($productConcreteTransfer->getStocks());
492
        foreach ($productConcreteTransfer->getStocks() as $stock) {
493
            $this->assertNotEquals($this->stockTransfer2->getIdStock(), $stock->getFkStock(), 'Stock ID did not match expected value.');
494
        }
495
    }
496
497
    /**
498
     * @return void
499
     */
500
    public function testGetAvailableStockTypesWillReturnCollectionOfStockNamesIndexedByStoreNames(): void
501
    {
502
        //Arrange
503
        $this->stockEntity2->setIsActive(false)->save();
504
505
        //Act
506
        $stocks = $this->stockFacade->getAvailableStockTypes();
507
508
        //Assert
509
        $this->assertArrayHasKey($this->stockTransfer1->getName(), $stocks, 'Available stock types collection does not match expected value.');
510
        $this->assertArrayHasKey($this->stockTransfer2->getName(), $stocks, 'Available stock types collection does not match expected value.');
511
        $this->assertContains($this->stockTransfer1->getName(), $stocks, 'Available stock types collection does not match expected value.');
512
        $this->assertContains($this->stockTransfer2->getName(), $stocks, 'Available stock types collection does not match expected value.');
513
    }
514
515
    /**
516
     * @return void
517
     */
518
    public function testGetStockProductsByIdProductWillReturnStockProductWhereStockIsActive(): void
519
    {
520
        //Arrange
521
        $this->stockEntity2->setIsActive(false)->save();
522
523
        //Act
524
        $stockProductTransfers = $this->stockFacade->getStockProductsByIdProduct($this->productConcreteEntity->getIdProduct());
525
526
        //Assert
527
        $this->assertCount(1, $stockProductTransfers, 'Stock products count does not match expected value.');
528
        $this->assertTrue(
529
            $stockProductTransfers[0]->getQuantity()->equals(static::STOCK_QUANTITY_1),
530
            'Stock product quantity does not match expected value.',
531
        );
532
        $this->assertSame(
533
            $this->stockTransfer1->getIdStock(),
534
            $stockProductTransfers[0]->getFkStock(),
535
            'Stock ID does not match expected value.',
536
        );
537
    }
538
539
    /**
540
     * @return void
541
     */
542
    public function testGetStockTypesForStoreWillReturnCollectionOfStockNamesIndexedByStockName(): void
543
    {
544
        //Act
545
        $stockCollection = $this->stockFacade->getStockTypesForStore($this->storeTransfer);
546
547
        //Assert
548
        $this->assertIsArray($stockCollection, 'Stock types collection should be an array.');
549
        $this->assertArrayHasKey($this->stockTransfer1->getName(), $stockCollection, 'Stock types collection does not match expected value.');
550
        $this->assertContains($this->stockTransfer1->getName(), $stockCollection, 'Stock types collection does not match expected value.');
551
    }
552
553
    /**
554
     * @return void
555
     */
556
    public function testGetWarehouseToStoreMappingWillReturnCollectionOfStocksWithCollectionOfStoresNamesIndexedByStoresName(): void
557
    {
558
        //Arrange
559
        $this->tester->haveStockStoreRelation(
560
            (new StockTransfer())->fromArray($this->stockEntity2->toArray(), true),
561
            $this->storeTransfer,
562
        );
563
564
        //Act
565
        $stockCollection = $this->stockFacade->getWarehouseToStoreMapping();
566
567
        //Assert
568
        $this->assertIsArray($stockCollection, 'Warehouse to store mapping collection should be an array.');
569
        $storeName = $this->storeTransfer->getName();
570
        $this->assertArrayHasKey($this->stockTransfer1->getName(), $stockCollection, 'Warehouse to store mapping collection does not match expected value.');
571
        $this->assertArrayHasKey($this->stockTransfer2->getName(), $stockCollection, 'Warehouse to store mapping collection does not match expected value.');
572
        $this->assertEquals([
573
            $storeName => $storeName,
574
        ], $stockCollection[$this->stockTransfer1->getName()], 'Warehouse to store mapping collection does not match expected value.');
575
        $this->assertEquals([
576
            $storeName => $storeName,
577
        ], $stockCollection[$this->stockTransfer2->getName()], 'Warehouse to store mapping collection does not match expected value.');
578
    }
579
580
    /**
581
     * @return void
582
     */
583
    public function testGetStoreToWarehouseMappingWillReturnCollectionOfStoreNamesWithCollectionOfStockNamesIndexedByStockName(): void
584
    {
585
        //Arrange
586
        /** @var \Generated\Shared\Transfer\StoreTransfer $storeTransfer2 */
587
        $storeTransfer2 = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_AT]);
588
        $this->assignStockToStore($storeTransfer2, $this->stockTransfer1);
589
        $this->assignStockToStore($storeTransfer2, $this->stockTransfer2);
590
591
        //Act
592
        $storeToWarehouseMapping = $this->stockFacade->getStoreToWarehouseMapping();
593
594
        //Assert
595
        $this->assertArrayHasKey(
596
            $this->storeTransfer->getName(),
597
            $storeToWarehouseMapping,
598
            'Store to warehouse mapping collection does not have expected key.',
599
        );
600
        $this->assertContains(
601
            $this->stockTransfer1->getName(),
602
            $storeToWarehouseMapping[$this->storeTransfer->getName()],
603
            'Store to warehouse mapping collection does not match expected value.',
604
        );
605
606
        $this->assertArrayHasKey(
607
            $storeTransfer2->getName(),
608
            $storeToWarehouseMapping,
609
            'Store to warehouse mapping collection does not have expected key.',
610
        );
611
        $this->assertContains(
612
            $this->stockTransfer1->getName(),
613
            $storeToWarehouseMapping[$storeTransfer2->getName()],
614
            'Store to warehouse mapping collection does not match expected value.',
615
        );
616
        $this->assertContains(
617
            $this->stockTransfer2->getName(),
618
            $storeToWarehouseMapping[$storeTransfer2->getName()],
619
            'Store to warehouse mapping collection does not match expected value.',
620
        );
621
    }
622
623
    /**
624
     * @return void
625
     */
626
    public function testFindStockProductsByIdProductForStoreWillReturnCollectionOfStockProducts(): void
627
    {
628
        //Arrange
629
        $this->tester->haveStockStoreRelation($this->stockTransfer2, $this->storeTransfer);
630
631
        //Act
632
        $productStockCollection = $this->stockFacade->findStockProductsByIdProductForStore(
633
            $this->productConcreteEntity->getIdProduct(),
634
            $this->storeTransfer,
635
        );
636
637
        //Assert
638
        $this->assertIsArray($productStockCollection, 'Product stock collection should be an array.');
639
        $this->assertCount(2, $productStockCollection, 'Product stock collection count does not match expected value.');
640
        foreach ($productStockCollection as $stockProductTransfer) {
641
            $this->assertSame(
642
                $this->productConcreteEntity->getSku(),
643
                $stockProductTransfer->getSku(),
644
                'Concrete product sku of stock product does not match expected value.',
645
            );
646
        }
647
    }
648
649
    /**
650
     * @return void
651
     */
652
    public function testFindStockProductsByIdProductForStoreWillReturnCollectionOfStockProductsWithInactiveStocksIncluded(): void
653
    {
654
        //Arrange
655
        $this->tester->haveStockStoreRelation($this->stockTransfer2, $this->storeTransfer);
656
        $this->stockEntity2->setIsActive(false)->save();
657
658
        //Act
659
        $productStockCollection = $this->stockFacade->findStockProductsByIdProductForStore(
660
            $this->productConcreteEntity->getIdProduct(),
661
            $this->storeTransfer,
662
        );
663
664
        //Assert
665
        $this->assertIsArray($productStockCollection, 'Product stock collection should be an array.');
666
        $this->assertCount(2, $productStockCollection, 'Product stock collection count does not match expected value.');
667
        foreach ($productStockCollection as $stockProductTransfer) {
668
            $this->assertSame(
669
                $this->productConcreteEntity->getSku(),
670
                $stockProductTransfer->getSku(),
671
                'Concrete product sku of stock product does not match expected value.',
672
            );
673
        }
674
    }
675
676
    /**
677
     * @return void
678
     */
679
    public function testGetStoresWhereProductStockIsDefinedWillReturnArrayOfStoreTransfers(): void
680
    {
681
        //Act
682
        $storeTransfers = $this->stockFacade->getStoresWhereProductStockIsDefined(static::CONCRETE_SKU);
683
684
        //Assert
685
        $this->assertCount(1, $storeTransfers, 'Number of store does not match expected value.');
686
        $this->assertInstanceOf(
687
            StoreTransfer::class,
688
            $storeTransfers[0],
689
            sprintf('Store transfer should be an instance of %s.', StoreTransfer::class),
690
        );
691
        $this->assertSame(
692
            $this->storeTransfer->getIdStore(),
693
            $storeTransfers[0]->getIdStore(),
694
            'Store ID does not match expected value.',
695
        );
696
        $this->assertSame(
697
            $this->storeTransfer->getName(),
698
            $storeTransfers[0]->getName(),
699
            'Store name does not match expected value.',
700
        );
701
    }
702
703
    /**
704
     * @return void
705
     */
706
    public function testFindStockByNameWillFindExistingStock(): void
707
    {
708
        //Act
709
        $stockTransfer = $this->stockFacade->findStockByName($this->stockTransfer1->getName());
710
711
        //Assert
712
        $this->assertSame($stockTransfer->getIdStock(), $this->stockTransfer1->getIdStock(), 'Stock ID does not match expected value.');
713
        $this->assertSame($stockTransfer->getName(), $this->stockTransfer1->getName(), 'Stock name does not match expected value.');
714
    }
715
716
    /**
717
     * @return void
718
     */
719
    public function testFindStockByNameWillReturnNullForNonExistedStockName(): void
720
    {
721
        //Act
722
        $result = $this->stockFacade->findStockByName('Non-existing stock name');
723
724
        //Assert
725
        $this->assertNull($result, 'Result should be null.');
726
    }
727
728
    /**
729
     * @return void
730
     */
731
    public function testCreateStockWillCreateStock(): void
732
    {
733
        //Arrange
734
        $originStockTransfer = ((new StockBuilder())->build())
735
            ->setIsActive(false);
736
737
        //Act
738
        $stockResponseTransfer = $this->stockFacade->createStock($originStockTransfer);
739
740
        //Assert
741
        $this->assertTrue($stockResponseTransfer->getIsSuccessful(), 'Stock response should be successful.');
742
        $stockTransfer = $stockResponseTransfer->getStock();
743
        $this->assertIsInt($stockTransfer->getIdStock(), 'Stock ID should be integer value.');
744
        $this->assertSame($originStockTransfer->getName(), $stockTransfer->getName(), 'Stock name does not match expected value.');
745
        $this->assertSame($originStockTransfer->getIsActive(), $stockTransfer->getIsActive(), 'Stock active status does not match expected value.');
746
    }
747
748
    /**
749
     * @return void
750
     */
751
    public function testCreateStockWithRelationToStoreWillCreateStockWithRelations(): void
752
    {
753
        //Arrange
754
        $storeRelationTransfer = (new StoreRelationTransfer())
755
            ->setIdStores([$this->storeTransfer->getIdStore()]);
756
        $originStockTransfer = ((new StockBuilder())->build())
757
            ->setIsActive(false)
758
            ->setStoreRelation($storeRelationTransfer);
759
760
        //Act
761
        $stockResponseTransfer = $this->stockFacade->createStock($originStockTransfer);
762
        $storeStockRelation = $this->stockFacade->getStockTypesForStore($this->storeTransfer);
763
764
        //Assert
765
        $this->assertTrue($stockResponseTransfer->getIsSuccessful(), 'Stock response should be successful.');
766
        $stockTransfer = $stockResponseTransfer->getStock();
767
        $this->assertIsInt($stockTransfer->getIdStock(), 'Stock ID should be integer value.');
768
        $this->assertSame($originStockTransfer->getName(), $stockTransfer->getName(), 'Stock name does not match expected value.');
769
        $this->assertSame($originStockTransfer->getIsActive(), $stockTransfer->getIsActive(), 'Stock active status does not match expected value.');
770
        $this->assertNotNull($stockTransfer->getStoreRelation(), 'Stock should have store relations.');
771
        $this->assertEquals(
772
            $storeRelationTransfer->getIdStores(),
773
            $stockTransfer->getStoreRelation()->getIdStores(),
774
            'IDs of related stores does not match expected value.',
775
        );
776
        $this->assertContains($stockTransfer->getName(), $storeStockRelation, 'Store relation does not contain expected store name.');
777
    }
778
779
    /**
780
     * @return void
781
     */
782
    public function testFindStockByIdShouldReturnStockTransferForExistingStockId(): void
783
    {
784
        //Act
785
        $stockTransfer = $this->stockFacade->findStockById($this->stockTransfer1->getIdStock());
786
787
        //Assert
788
        $this->assertSame($this->stockTransfer1->getIdStock(), $stockTransfer->getIdStock(), 'Stock ID should be integer value.');
789
        $this->assertSame($this->stockTransfer1->getName(), $stockTransfer->getName(), 'Stock name does not match expected value.');
790
        $this->assertSame($this->stockTransfer1->getIsActive(), $stockTransfer->getIsActive(), 'Stock active status does not match expected value.');
791
    }
792
793
    /**
794
     * @return void
795
     */
796
    public function testFindStockByIdShouldReturnNullForNonExistingStockId(): void
797
    {
798
        //Act
799
        $result = $this->stockFacade->findStockById(-1);
800
801
        //Assert
802
        $this->assertNull($result, 'The result must be null');
803
    }
804
805
    /**
806
     * @return void
807
     */
808
    public function testUpdateStockShouldUpdateStockName(): void
809
    {
810
        //Arrange
811
        $newStockName = 'new name';
812
        $originStockTransfer = $this->tester->haveStock();
813
        $originStockTransfer->setName($newStockName);
814
815
        //Act
816
        $stockResponseTransfer = $this->stockFacade->updateStock($originStockTransfer);
817
818
        //Assert
819
        $this->assertTrue($stockResponseTransfer->getIsSuccessful(), 'Stock response should be successful.');
820
        $stockTransfer = $stockResponseTransfer->getStock();
821
        $this->assertSame($newStockName, $stockTransfer->getName(), 'Stock name does not match expected value.');
822
    }
823
824
    /**
825
     * @return void
826
     */
827
    public function testUpdateStockShouldUpdateStockStatus(): void
828
    {
829
        //Arrange
830
        $originStockTransfer = $this->stockTransfer1;
831
        $originStockTransfer->setIsActive(false);
832
833
        //Act
834
        $stockResponseTransfer = $this->stockFacade->updateStock($originStockTransfer);
835
836
        //Assert
837
        $this->assertTrue($stockResponseTransfer->getIsSuccessful(), 'Stock response should be successful.');
838
        $stockTransfer = $stockResponseTransfer->getStock();
839
        $this->assertSame($originStockTransfer->getIsActive(), $stockTransfer->getIsActive(), 'Stock active status does not match expected value.');
840
    }
841
842
    /**
843
     * @return void
844
     */
845
    public function testUpdateStockShouldAddStoreRelations(): void
846
    {
847
        //Arrange
848
        $storeRelationTransfer = (new StoreRelationTransfer())
849
            ->setIdStores([$this->storeTransfer->getIdStore()]);
850
        $originStockTransfer = $this->stockTransfer2;
851
        $originStockTransfer->setStoreRelation($storeRelationTransfer);
852
853
        //Act
854
        $stockResponseTransfer = $this->stockFacade->updateStock($originStockTransfer);
855
        $storeStockRelation = $this->stockFacade->getStockTypesForStore($this->storeTransfer);
856
857
        //Assert
858
        $this->assertTrue($stockResponseTransfer->getIsSuccessful(), 'Stock response should be successful.');
859
        $stockTransfer = $stockResponseTransfer->getStock();
860
        $this->assertContains($stockTransfer->getName(), $storeStockRelation, 'Store relation does not contain expected store name.');
861
    }
862
863
    /**
864
     * @return void
865
     */
866
    public function testUpdateStockShouldRemoveStoreRelations(): void
867
    {
868
        //Arrange
869
        $storeRelationTransfer = (new StoreRelationTransfer())->setIdStores([]);
870
        $originStockTransfer = $this->stockTransfer1;
871
        $originStockTransfer->setStoreRelation($storeRelationTransfer);
872
873
        //Act
874
        $stockResponseTransfer = $this->stockFacade->updateStock($originStockTransfer);
875
        $storeStockRelation = $this->stockFacade->getStockTypesForStore($this->storeTransfer);
876
877
        //Assert
878
        $this->assertTrue($stockResponseTransfer->getIsSuccessful(), 'Stock response should be successful.');
879
        $stockTransfer = $stockResponseTransfer->getStock();
880
        $this->assertNotContains($stockTransfer->getName(), $storeStockRelation, 'Store relation should not contain store name.');
881
    }
882
883
    /**
884
     * @return void
885
     */
886
    public function testGetStocksByStockCriteriaFilterWillFilterStocksByName(): void
887
    {
888
        // Arrange
889
        $stockCriteriaFilterTransfer = (new StockCriteriaFilterTransfer())
890
            ->setIdStock($this->stockEntity1->getIdStock())
891
            ->addStockName($this->stockEntity1->getName());
892
893
        // Act
894
        $stockCollectionTransfer = $this->stockFacade->getStocksByStockCriteriaFilter($stockCriteriaFilterTransfer);
895
896
        // Assert
897
        $this->assertCount(1, $stockCollectionTransfer->getStocks(), 'Stocks count does not match expected value.');
898
        $this->assertSame(
899
            $this->stockEntity1->getName(),
900
            $stockCollectionTransfer->getStocks()->offsetGet(0)->getNameOrFail(),
901
            'Stock name does not match expected value.',
902
        );
903
    }
904
905
    /**
906
     * @return void
907
     */
908
    public function testGetStocksByStockCriteriaFilterWillReturnEmptyCollectionForNonExistingStockName(): void
909
    {
910
        // Arrange
911
        $stockCriteriaFilterTransfer = (new StockCriteriaFilterTransfer())->addStockName('SOME_RANDOM_STOCK_NAME');
912
913
        // Act
914
        $stockCollectionTransfer = $this->stockFacade->getStocksByStockCriteriaFilter($stockCriteriaFilterTransfer);
915
916
        // Assert
917
        $this->assertCount(0, $stockCollectionTransfer->getStocks(), 'Stocks count does not match expected value.');
918
    }
919
920
    /**
921
     * @return void
922
     */
923
    public function testGetStocksByStockCriteriaFilterWillReturnEmptyCollectionForNonExistingStockId(): void
924
    {
925
        // Arrange
926
        $stockCriteriaFilterTransfer = (new StockCriteriaFilterTransfer())->setIdStock(static::INVALID_STOCK_ID);
927
928
        // Act
929
        $stockCollectionTransfer = $this->stockFacade->getStocksByStockCriteriaFilter($stockCriteriaFilterTransfer);
930
931
        // Assert
932
        $this->assertCount(0, $stockCollectionTransfer->getStocks(), 'Stocks count does not match expected value.');
933
    }
934
935
    /**
936
     * @return void
937
     */
938
    public function testGetStocksByStockCriteriaFilterWillFilterStocksByActiveStatus(): void
939
    {
940
        // Arrange
941
        $stockCriteriaFilterTransfer = (new StockCriteriaFilterTransfer())->setIsActive(true);
942
943
        // Act
944
        $stockCollectionTransfer = $this->stockFacade->getStocksByStockCriteriaFilter($stockCriteriaFilterTransfer);
945
946
        // Assert
947
        $this->assertGreaterThanOrEqual(2, $stockCollectionTransfer->getStocks()->count(), 'Stocks count does not match expected value.');
948
949
        $resultStockNames = array_map(function (StockTransfer $stockTransfer) {
950
            return $stockTransfer->getNameOrFail();
951
        }, $stockCollectionTransfer->getStocks()->getArrayCopy());
952
        $this->assertTrue(in_array($this->stockEntity1->getName(), $resultStockNames, true), 'Expected stock name is missing in returned stock collection.');
953
        $this->assertTrue(in_array($this->stockEntity2->getName(), $resultStockNames, true), 'Expected stock name is missing in returned stock collection.');
954
    }
955
956
    /**
957
     * @return void
958
     */
959
    public function testGetStocksByStockCriteriaFilterWillFilterStocksByStoreName(): void
960
    {
961
        // Arrange
962
        $storeTransfer = $this->tester->haveStore([StoreTransfer::NAME => static::STORE_NAME_DE]);
963
        $this->tester->haveStockStoreRelation($this->stockTransfer1, $storeTransfer);
964
965
        $stockCriteriaFilterTransfer = (new StockCriteriaFilterTransfer())->addStoreName(static::STORE_NAME_DE)->setIsActive(true);
966
967
        // Act
968
        $stockCollectionTransfer = $this->stockFacade->getStocksByStockCriteriaFilter($stockCriteriaFilterTransfer);
969
        $availableStocksForStore = $this->stockFacade->getAvailableWarehousesForStore($storeTransfer);
970
971
        // Assert
972
        $this->assertCount(count($availableStocksForStore), $stockCollectionTransfer->getStocks(), 'Stocks count does not match expected value.');
973
    }
974
975
    /**
976
     * @return void
977
     */
978
    public function testGetStockStoreCollectionSuccessful(): void
979
    {
980
        // Arrange
981
        $storeTransferDE = $this->tester->haveStore([
982
            StoreTransfer::NAME => static::STORE_NAME_DE,
983
        ]);
984
        $storeTransferAT = $this->tester->haveStore([
985
            StoreTransfer::NAME => static::STORE_NAME_AT,
986
        ]);
987
988
        $stockTransferDE = $this->tester->haveStock([StockTransfer::NAME => 'StockDE']);
989
        $stockTransferAT = $this->tester->haveStock([StockTransfer::NAME => 'StockAT']);
990
991
        $this->tester->haveStockStoreRelation($stockTransferDE, $storeTransferDE);
992
        $this->tester->haveStockStoreRelation($stockTransferAT, $storeTransferAT);
993
994
        // Act
995
        $stockStoreCollectionTransfer = $this->stockFacade->getStockStoreCollection(new StockStoreCriteriaTransfer());
996
997
        // Assert
998
        $this->assertNotEmpty($stockStoreCollectionTransfer->getStockStores());
999
        $stockIdsGroupedByIdStore = [];
1000
        foreach ($stockStoreCollectionTransfer->getStockStores() as $stockStoreTransfer) {
1001
            $stockIdsGroupedByIdStore[$stockStoreTransfer->getFkStore()][] = $stockStoreTransfer->getFkStock();
1002
        }
1003
1004
        $this->assertTrue(isset($stockIdsGroupedByIdStore[$storeTransferDE->getIdStore()]));
1005
        $this->assertTrue(isset($stockIdsGroupedByIdStore[$storeTransferAT->getIdStore()]));
1006
        $this->assertTrue(in_array($stockTransferDE->getIdStock(), $stockIdsGroupedByIdStore[$storeTransferDE->getIdStore()]));
1007
        $this->assertTrue(in_array($stockTransferAT->getIdStock(), $stockIdsGroupedByIdStore[$storeTransferAT->getIdStore()]));
1008
    }
1009
1010
    /**
1011
     * @return void
1012
     */
1013
    public function testGetStockStoreCollectionWithoutRelation(): void
1014
    {
1015
        // Arrange
1016
        $storeTransferTest = $this->tester->haveStore([
1017
            StoreTransfer::NAME => static::STORE_NAME_TEST_STORE,
1018
        ]);
1019
1020
        // Act
1021
        $stockStoreCollectionTransfer = $this->stockFacade->getStockStoreCollection(new StockStoreCriteriaTransfer());
1022
1023
        // Assert
1024
        $stockIdsGroupedByIdStore = [];
1025
        foreach ($stockStoreCollectionTransfer->getStockStores() as $stockStoreTransfer) {
1026
            $stockIdsGroupedByIdStore[$stockStoreTransfer->getFkStore()][] = $stockStoreTransfer->getFkStock();
1027
        }
1028
        $this->assertFalse(isset($stockIdsGroupedByIdStore[$storeTransferTest->getIdStore()]));
1029
    }
1030
1031
    /**
1032
     * @return void
1033
     */
1034
    public function testUpdateStockShouldNotUpdateStockProductsAndStoreRelationWhenOnlyNameChanged(): void
1035
    {
1036
        // Arrange
1037
        $this->tester->mockConfigMethod('isConditionalStockUpdateApplied', true);
1038
        $originStockTransfer = $this->tester->haveStock();
1039
        $originStockTransfer->setName('Changed Name');
1040
1041
        $touchFacade = $this->getMockBuilder(StockToTouchInterface::class)
1042
            ->onlyMethods(['touchActive'])
1043
            ->getMock();
1044
        $touchFacade->expects($this->never())->method('touchActive');
1045
1046
        $stockProductUpdater = $this->getMockBuilder(StockProductUpdaterInterface::class)
1047
            ->onlyMethods(['updateStockProductsRelatedToStock'])
1048
            ->getMock();
1049
        $stockProductUpdater->expects($this->never())->method('updateStockProductsRelatedToStock');
1050
1051
        $stockStoreRelationshipUpdater = $this->getMockBuilder(StockStoreRelationshipUpdaterInterface::class)
1052
            ->onlyMethods(['updateStockStoreRelationshipsForStock'])
1053
            ->getMock();
1054
        $stockStoreRelationshipUpdater->expects($this->never())->method('updateStockStoreRelationshipsForStock');
1055
1056
        // Mock the createStockUpdater method
1057
        $this->tester->mockFactoryMethod('createStockUpdater', new StockUpdater(
1058
            new StockEntityManager(),
1059
            new StockRepository(),
1060
            $touchFacade,
1061
            $stockStoreRelationshipUpdater,
1062
            $stockProductUpdater,
1063
            $this->tester->getModuleConfig(),
1064
            [],
1065
            $this->createMock(StockToEventFacadeInterface::class),
1066
        ));
1067
1068
        // Act
1069
        $response = $this->tester->getFacade()->updateStock($originStockTransfer);
1070
1071
        // Assert
1072
        $this->assertTrue($response->getIsSuccessful());
1073
        $this->assertSame('Changed Name', $response->getStock()->getName());
1074
    }
1075
1076
    /**
1077
     * @return void
1078
     */
1079
    public function testUpdateStockShouldNotUpdateStockProductsAndStoreRelationWhenShouldUpdateStockRelationsAsyncEnabled(): void
1080
    {
1081
        // Arrange
1082
        $originStockTransfer = $this->tester->haveStock();
1083
        $originStockTransfer
1084
            ->setName('Changed Name')
1085
            ->setShouldUpdateStockRelationsAsync(true);
1086
1087
        $touchFacade = $this->getMockBuilder(StockToTouchInterface::class)
1088
            ->onlyMethods(['touchActive'])
1089
            ->getMock();
1090
        $touchFacade->expects($this->once())->method('touchActive');
1091
1092
        $stockProductUpdater = $this->getMockBuilder(StockProductUpdaterInterface::class)
1093
            ->onlyMethods(['updateStockProductsRelatedToStock'])
1094
            ->getMock();
1095
        $stockProductUpdater->expects($this->never())->method('updateStockProductsRelatedToStock');
1096
1097
        $stockStoreRelationshipUpdater = $this->getMockBuilder(StockStoreRelationshipUpdaterInterface::class)
1098
            ->onlyMethods(['updateStockStoreRelationshipsForStock'])
1099
            ->getMock();
1100
        $stockStoreRelationshipUpdater->expects($this->once())->method('updateStockStoreRelationshipsForStock');
1101
1102
        $eventFacade = $this->getMockBuilder(StockToEventFacadeInterface::class)
1103
            ->onlyMethods(['trigger'])
1104
            ->getMock();
1105
        $eventFacade->expects($this->once())->method('trigger');
1106
1107
        // Mock the createStockUpdater method
1108
        $this->tester->mockFactoryMethod('createStockUpdater', new StockUpdater(
1109
            new StockEntityManager(),
1110
            new StockRepository(),
1111
            $touchFacade,
1112
            $stockStoreRelationshipUpdater,
1113
            $stockProductUpdater,
1114
            $this->tester->getModuleConfig(),
1115
            [],
1116
            $eventFacade,
1117
        ));
1118
1119
        // Act
1120
        $response = $this->tester->getFacade()->updateStock($originStockTransfer);
1121
1122
        // Assert
1123
        $this->assertTrue($response->getIsSuccessful());
1124
        $this->assertSame('Changed Name', $response->getStock()->getName());
1125
    }
1126
1127
    /**
1128
     * @return void
1129
     */
1130
    public function testUpdateStockShouldNotUpdateStockProductsAndStoreRelationWhenShouldUpdateStockRelationsAsyncDisabled(): void
1131
    {
1132
        // Arrange
1133
        $originStockTransfer = $this->tester->haveStock();
1134
        $originStockTransfer
1135
            ->setName('Changed Name')
1136
            ->setShouldUpdateStockRelationsAsync(false);
1137
1138
        $touchFacade = $this->getMockBuilder(StockToTouchInterface::class)
1139
            ->onlyMethods(['touchActive'])
1140
            ->getMock();
1141
        $touchFacade->expects($this->once())->method('touchActive');
1142
1143
        $stockProductUpdater = $this->getMockBuilder(StockProductUpdaterInterface::class)
1144
            ->onlyMethods(['updateStockProductsRelatedToStock'])
1145
            ->getMock();
1146
        $stockProductUpdater->expects($this->once())->method('updateStockProductsRelatedToStock');
1147
1148
        $stockStoreRelationshipUpdater = $this->getMockBuilder(StockStoreRelationshipUpdaterInterface::class)
1149
            ->onlyMethods(['updateStockStoreRelationshipsForStock'])
1150
            ->getMock();
1151
        $stockStoreRelationshipUpdater->expects($this->once())->method('updateStockStoreRelationshipsForStock');
1152
1153
        $eventFacade = $this->getMockBuilder(StockToEventFacadeInterface::class)
1154
            ->onlyMethods(['trigger'])
1155
            ->getMock();
1156
        $eventFacade->expects($this->never())->method('trigger');
1157
1158
        // Mock the createStockUpdater method
1159
        $this->tester->mockFactoryMethod('createStockUpdater', new StockUpdater(
1160
            new StockEntityManager(),
1161
            new StockRepository(),
1162
            $touchFacade,
1163
            $stockStoreRelationshipUpdater,
1164
            $stockProductUpdater,
1165
            $this->tester->getModuleConfig(),
1166
            [],
1167
            $eventFacade,
1168
        ));
1169
1170
        // Act
1171
        $response = $this->tester->getFacade()->updateStock($originStockTransfer);
1172
1173
        // Assert
1174
        $this->assertTrue($response->getIsSuccessful());
1175
        $this->assertSame('Changed Name', $response->getStock()->getName());
1176
    }
1177
1178
    /**
1179
     * @return void
1180
     */
1181
    public function testUpdateStockShouldUpdateStockProductsWhenIsActiveChanged(): void
1182
    {
1183
        // Arrange
1184
        $this->tester->mockConfigMethod('isConditionalStockUpdateApplied', true);
1185
        $originStockTransfer = $this->tester->haveStock();
1186
        $originStockTransfer->setIsActive(!$originStockTransfer->getIsActive());
1187
1188
        $touchFacade = $this->getMockBuilder(StockToTouchInterface::class)
1189
            ->onlyMethods(['touchActive'])
1190
            ->getMock();
1191
        $touchFacade->expects($this->once())->method('touchActive');
1192
1193
        $stockProductUpdater = $this->getMockBuilder(StockProductUpdaterInterface::class)
1194
            ->onlyMethods(['updateStockProductsRelatedToStock'])
1195
            ->getMock();
1196
        $stockProductUpdater->expects($this->once())->method('updateStockProductsRelatedToStock');
1197
1198
        $stockStoreRelationshipUpdater = $this->getMockBuilder(StockStoreRelationshipUpdaterInterface::class)->getMock();
1199
1200
        // Mock the createStockUpdater method
1201
        $this->tester->mockFactoryMethod('createStockUpdater', new StockUpdater(
1202
            new StockEntityManager(),
1203
            new StockRepository(),
1204
            $touchFacade,
1205
            $stockStoreRelationshipUpdater,
1206
            $stockProductUpdater,
1207
            $this->tester->getModuleConfig(),
1208
            [],
1209
            $this->createMock(StockToEventFacadeInterface::class),
1210
        ));
1211
1212
        // Act
1213
        $response = $this->tester->getFacade()->updateStock($originStockTransfer);
1214
1215
        // Assert
1216
        $this->assertTrue($response->getIsSuccessful());
1217
        $this->assertSame($originStockTransfer->getIsActive(), $response->getStock()->getIsActive());
1218
    }
1219
1220
    /**
1221
     * @return void
1222
     */
1223
    public function testUpdateStockShouldUpdateStoreRelationWhenStoreRelationChanged(): void
1224
    {
1225
        // Arrange
1226
        $this->tester->mockConfigMethod('isConditionalStockUpdateApplied', true);
1227
        $originStockTransfer = $this->tester->haveStock();
1228
        $storeRelationTransfer = (new StoreRelationTransfer())->setIdStores([$this->storeTransfer->getIdStore()]);
1229
        $originStockTransfer->setStoreRelation($storeRelationTransfer);
1230
1231
        $touchFacade = $this->getMockBuilder(StockToTouchInterface::class)
1232
            ->onlyMethods(['touchActive'])
1233
            ->getMock();
1234
        $touchFacade->expects($this->once())->method('touchActive');
1235
1236
        $stockProductUpdater = $this->getMockBuilder(StockProductUpdaterInterface::class)
1237
            ->onlyMethods(['updateStockProductsRelatedToStock'])
1238
            ->getMock();
1239
        $stockProductUpdater->expects($this->once())->method('updateStockProductsRelatedToStock');
1240
1241
        $stockStoreRelationshipUpdater = $this->getMockBuilder(StockStoreRelationshipUpdaterInterface::class)
1242
            ->onlyMethods(['updateStockStoreRelationshipsForStock'])
1243
            ->getMock();
1244
        $stockStoreRelationshipUpdater->expects($this->once())->method('updateStockStoreRelationshipsForStock');
1245
1246
        // Mock the createStockUpdater method
1247
        $this->tester->mockFactoryMethod('createStockUpdater', new StockUpdater(
1248
            new StockEntityManager(),
1249
            new StockRepository(),
1250
            $touchFacade,
1251
            $stockStoreRelationshipUpdater,
1252
            $stockProductUpdater,
1253
            $this->tester->getModuleConfig(),
1254
            [],
1255
            $this->createMock(StockToEventFacadeInterface::class),
1256
        ));
1257
1258
        // Act
1259
        $response = $this->tester->getFacade()->updateStock($originStockTransfer);
1260
1261
        // Assert
1262
        $this->assertTrue($response->getIsSuccessful());
1263
        $this->assertEquals(
1264
            $storeRelationTransfer->getIdStores(),
1265
            $response->getStock()->getStoreRelation()->getIdStores(),
1266
        );
1267
    }
1268
1269
    /**
1270
     * @return void
1271
     */
1272
    protected function setupData(): void
1273
    {
1274
        $this->storeTransfer = $this->tester->haveStore([
1275
            StoreTransfer::NAME => static::STORE_NAME_DE,
1276
        ]);
1277
1278
        $this->productAbstractEntity = new SpyProductAbstract();
1279
        $this->productAbstractEntity
1280
            ->setSku(static::ABSTRACT_SKU)
1281
            ->setAttributes('{}')
1282
            ->save();
1283
1284
        $this->productConcreteEntity = new SpyProduct();
1285
        $this->productConcreteEntity
1286
            ->setSku(static::CONCRETE_SKU)
1287
            ->setAttributes('{}')
1288
            ->setFkProductAbstract($this->productAbstractEntity->getIdProductAbstract())
1289
            ->save();
1290
1291
        $this->stockEntity1 = new SpyStock();
1292
        $this->stockEntity1
1293
            ->setName('TEST')
1294
            ->save();
1295
        $this->stockTransfer1 = $this->mapStockEntityToStockTransfer($this->stockEntity1, new StockTransfer());
1296
        $this->assignStockToStore($this->storeTransfer, $this->stockTransfer1);
1297
1298
        $this->productStockEntity1 = new SpyStockProduct();
1299
        $this->productStockEntity1
1300
            ->setFkStock($this->stockEntity1->getIdStock())
1301
            ->setQuantity(static::STOCK_QUANTITY_1)
1302
            ->setIsNeverOutOfStock(false)
1303
            ->setFkProduct($this->productConcreteEntity->getIdProduct())
1304
            ->save();
1305
1306
        $this->stockEntity2 = new SpyStock();
1307
        $this->stockEntity2
1308
            ->setName('TEST2')
1309
            ->save();
1310
        $this->stockTransfer2 = $this->mapStockEntityToStockTransfer($this->stockEntity2, new StockTransfer());
1311
1312
        $this->productStockEntity2 = new SpyStockProduct();
1313
        $this->productStockEntity2
1314
            ->setFkStock($this->stockEntity2->getIdStock())
1315
            ->setQuantity(static::STOCK_QUANTITY_2)
1316
            ->setIsNeverOutOfStock(false)
1317
            ->setFkProduct($this->productConcreteEntity->getIdProduct())
1318
            ->save();
1319
    }
1320
1321
    /**
1322
     * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer
1323
     * @param \Generated\Shared\Transfer\StockTransfer $stockTransfer
1324
     *
1325
     * @return void
1326
     */
1327
    protected function assignStockToStore(StoreTransfer $storeTransfer, StockTransfer $stockTransfer): void
1328
    {
1329
        $this->tester->haveStockStoreRelation(
1330
            $stockTransfer,
1331
            $storeTransfer,
1332
        );
1333
    }
1334
1335
    /**
1336
     * @param \Orm\Zed\Stock\Persistence\SpyStock $stockEntity
1337
     * @param \Generated\Shared\Transfer\StockTransfer $stockTransfer
1338
     *
1339
     * @return \Generated\Shared\Transfer\StockTransfer
1340
     */
1341
    protected function mapStockEntityToStockTransfer(SpyStock $stockEntity, StockTransfer $stockTransfer): StockTransfer
1342
    {
1343
        return $stockTransfer->fromArray($stockEntity->toArray(), true);
1344
    }
1345
}
1346