CheckoutApiTester::getCartFacade()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of the Spryker Commerce OS.
5
 * For full license information, please view the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types = 1);
9
10
namespace PyzTest\Glue\Checkout;
11
12
use ArrayObject;
13
use DateTime;
14
use Generated\Shared\DataBuilder\AddressBuilder;
15
use Generated\Shared\DataBuilder\CustomerBuilder;
16
use Generated\Shared\DataBuilder\ItemBuilder;
17
use Generated\Shared\DataBuilder\MerchantBuilder;
18
use Generated\Shared\DataBuilder\ServicePointBuilder;
19
use Generated\Shared\DataBuilder\ShipmentBuilder;
20
use Generated\Shared\DataBuilder\StoreRelationBuilder;
21
use Generated\Shared\Transfer\AddressTransfer;
22
use Generated\Shared\Transfer\CountryTransfer;
23
use Generated\Shared\Transfer\CustomerTransfer;
24
use Generated\Shared\Transfer\ItemTransfer;
25
use Generated\Shared\Transfer\MerchantProfileTransfer;
26
use Generated\Shared\Transfer\MerchantTransfer;
27
use Generated\Shared\Transfer\MoneyValueTransfer;
28
use Generated\Shared\Transfer\PaymentMethodTransfer;
29
use Generated\Shared\Transfer\PriceProductOfferTransfer;
30
use Generated\Shared\Transfer\PriceProductTransfer;
31
use Generated\Shared\Transfer\ProductConcreteTransfer;
32
use Generated\Shared\Transfer\ProductOfferServiceTransfer;
33
use Generated\Shared\Transfer\ProductOfferStockTransfer;
34
use Generated\Shared\Transfer\ProductOfferTransfer;
35
use Generated\Shared\Transfer\QuoteTransfer;
36
use Generated\Shared\Transfer\RestAddressTransfer;
37
use Generated\Shared\Transfer\RestCheckoutDataTransfer;
38
use Generated\Shared\Transfer\RestCheckoutResponseTransfer;
39
use Generated\Shared\Transfer\RestCustomerTransfer;
40
use Generated\Shared\Transfer\RestOrderDetailsAttributesTransfer;
41
use Generated\Shared\Transfer\RestPaymentTransfer;
42
use Generated\Shared\Transfer\RestServicePointTransfer;
43
use Generated\Shared\Transfer\RestShipmentsTransfer;
44
use Generated\Shared\Transfer\RestShipmentTransfer;
45
use Generated\Shared\Transfer\ServicePointAddressTransfer;
46
use Generated\Shared\Transfer\ServicePointTransfer;
47
use Generated\Shared\Transfer\ServiceTransfer;
48
use Generated\Shared\Transfer\ServiceTypeTransfer;
49
use Generated\Shared\Transfer\ShipmentMethodTransfer;
50
use Generated\Shared\Transfer\ShipmentTransfer;
51
use Generated\Shared\Transfer\ShipmentTypeTransfer;
52
use Generated\Shared\Transfer\StockProductTransfer;
53
use Generated\Shared\Transfer\StockTransfer;
54
use Generated\Shared\Transfer\StoreRelationTransfer;
55
use Generated\Shared\Transfer\StoreTransfer;
56
use Generated\Shared\Transfer\TotalsTransfer;
57
use Orm\Zed\Sales\Persistence\SpySalesOrderAddress;
58
use Orm\Zed\Sales\Persistence\SpySalesOrderAddressQuery;
59
use Orm\Zed\ServicePoint\Persistence\SpyServiceTypeQuery;
60
use Orm\Zed\Shipment\Persistence\SpyShipmentMethodQuery;
61
use Orm\Zed\ShipmentType\Persistence\SpyShipmentTypeQuery;
62
use Orm\Zed\ShipmentTypeServicePoint\Persistence\SpyShipmentTypeServiceTypeQuery;
63
use Spryker\Glue\CheckoutRestApi\CheckoutRestApiConfig;
64
use Spryker\Glue\GlueApplication\Rest\RequestConstantsInterface;
65
use Spryker\Glue\OrdersRestApi\OrdersRestApiConfig;
66
use Spryker\Shared\Price\PriceConfig;
67
use Spryker\Shared\Shipment\ShipmentConfig;
68
use Spryker\Zed\Cart\Business\CartFacadeInterface;
69
use Spryker\Zed\Customer\Business\CustomerFacadeInterface;
70
use Spryker\Zed\Store\Business\StoreFacadeInterface;
71
use SprykerTest\Glue\Testify\Tester\ApiEndToEndTester;
72
73
/**
74
 * Inherited Methods
75
 *
76
 * @method void wantToTest($text)
77
 * @method void wantTo($text)
78
 * @method void execute($callable)
79
 * @method void expectTo($prediction)
80
 * @method void expect($prediction)
81
 * @method void amGoingTo($argumentation)
82
 * @method void am($role)
83
 * @method void lookForwardTo($achieveValue)
84
 * @method void comment($description)
85
 * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = null)
86
 *
87
 * @SuppressWarnings(\PyzTest\Glue\Checkout\PHPMD)
88
 */
89
class CheckoutApiTester extends ApiEndToEndTester
90
{
91
    use _generated\CheckoutApiTesterActions;
92
93
    /**
94
     * @uses \Spryker\Zed\Merchant\MerchantConfig::STATUS_APPROVED
95
     *
96
     * @var string
97
     */
98
    public const MERCHANT_STATUS_APPROVED = 'approved';
99
100
    /**
101
     * @var string
102
     */
103
    protected const REQUEST_PARAM_PAYMENT_METHOD_NAME_INVOICE = 'Invoice (Marketplace)';
104
105
    /**
106
     * @var string
107
     */
108
    protected const REQUEST_PARAM_PAYMENT_PROVIDER_NAME_DUMMY_PAYMENT = 'DummyMarketplacePayment';
109
110
    /**
111
     * @var string
112
     */
113
    protected const QUOTE_ITEM_OVERRIDE_DATA_PRODUCT = 'product';
114
115
    /**
116
     * @var string
117
     */
118
    protected const QUOTE_ITEM_OVERRIDE_DATA_PRODUCT_OFFER = 'product-offer';
119
120
    /**
121
     * @var string
122
     */
123
    protected const QUOTE_ITEM_OVERRIDE_DATA_SHIPMENT = 'shipment';
124
125
    /**
126
     * @var string
127
     */
128
    protected const QUOTE_ITEM_OVERRIDE_DATA_QUANTITY = 'quantity';
129
130
    /**
131
     * @var int
132
     */
133
    protected const DEFAULT_QUOTE_ITEM_QUANTITY = 10;
134
135
    /**
136
     * @var string
137
     */
138
    protected const TEST_STORE_NAME = 'DE';
139
140
    /**
141
     * @var string
142
     */
143
    protected const SHIPMENT_TYPE_KEY_PICKUP = 'pickup';
144
145
    /**
146
     * @var string
147
     */
148
    protected const COUNTRY_ISO2_CODE = 'XX';
149
150
    /**
151
     * @var string
152
     */
153
    protected const COUNTRY_ISO3_CODE = 'XXX';
154
155
    /**
156
     * @return void
157
     */
158
    public function assertCheckoutResponseResourceHasCorrectData(): void
159
    {
160
        $this->amSure('The returned resource id should be null')
161
            ->whenI()
162
            ->seeSingleResourceIdEqualTo('');
0 ignored issues
show
Bug introduced by
It seems like seeSingleResourceIdEqualTo() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

162
            ->/** @scrutinizer ignore-call */ seeSingleResourceIdEqualTo('');
Loading history...
163
164
        $attributes = $this->getDataFromResponseByJsonPath('$.data.attributes');
165
166
        $this->assertNotEmpty(
167
            $attributes[RestCheckoutResponseTransfer::ORDER_REFERENCE],
168
            'The returned resource attributes order reference should not be empty',
169
        );
170
        $this->assertArrayHasKey(
171
            RestCheckoutResponseTransfer::IS_EXTERNAL_REDIRECT,
172
            $attributes,
173
            'The returned resource attributes should have an external redirect key',
174
        );
175
        $this->assertArrayHasKey(
176
            RestCheckoutResponseTransfer::REDIRECT_URL,
177
            $attributes,
178
            'The returned resource attributes should have a redirect URL key',
179
        );
180
    }
181
182
    /**
183
     * @return void
184
     */
185
    public function assertCheckoutDataResponseResourceHasCorrectData(): void
186
    {
187
        $this->amSure('The returned resource id should be null')
188
            ->whenI()
189
            ->seeSingleResourceIdEqualTo('');
190
191
        $attributes = $this->getDataFromResponseByJsonPath('$.data.attributes');
192
193
        $this->assertEmpty(
194
            $attributes[RestCheckoutDataTransfer::ADDRESSES],
195
            'The returned resource attributes addresses should be an empty array',
196
        );
197
    }
198
199
    /**
200
     * @param \Generated\Shared\Transfer\ServicePointAddressTransfer $servicePointAddressTransfer
201
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
202
     * @param string $itemSku
203
     *
204
     * @return void
205
     */
206
    public function assertSalesOrderAddressIsCorrectForItem(
207
        ServicePointAddressTransfer $servicePointAddressTransfer,
208
        CustomerTransfer $customerTransfer,
209
        string $itemSku,
210
    ): void {
211
        $orderReference = $this->getDataFromResponseByJsonPath('$.data.attributes')[RestCheckoutResponseTransfer::ORDER_REFERENCE];
212
213
        $salesOrderShipmentAddressEntity = $this->findSalesOrderAddressEntity($orderReference, $itemSku);
214
        $this->assertNotNull($salesOrderShipmentAddressEntity);
215
        $this->assertSame($servicePointAddressTransfer->getAddress1OrFail(), $salesOrderShipmentAddressEntity->getAddress1());
216
        $this->assertSame($servicePointAddressTransfer->getAddress2OrFail(), $salesOrderShipmentAddressEntity->getAddress2());
217
        $this->assertSame($servicePointAddressTransfer->getZipCodeOrFail(), $salesOrderShipmentAddressEntity->getZipCode());
218
        $this->assertSame($servicePointAddressTransfer->getCountryOrFail()->getIdCountryOrFail(), $salesOrderShipmentAddressEntity->getFkCountry());
219
        $this->assertSame($servicePointAddressTransfer->getCityOrFail(), $salesOrderShipmentAddressEntity->getCity());
220
        $this->assertSame($customerTransfer->getFirstNameOrFail(), $salesOrderShipmentAddressEntity->getFirstName());
221
        $this->assertSame($customerTransfer->getLastNameOrFail(), $salesOrderShipmentAddressEntity->getLastName());
222
        $this->assertSame($customerTransfer->getSalutationOrFail(), $salesOrderShipmentAddressEntity->getSalutation());
223
    }
224
225
    /**
226
     * @param int $price
227
     *
228
     * @return void
229
     */
230
    public function assertShipmentExpensesHaveCorrectPrice(int $price): void
231
    {
232
        $this->amSure('The returned resource should have included orders resource')
233
            ->whenI()
234
            ->seeIncludesContainResourceOfType(OrdersRestApiConfig::RESOURCE_ORDERS);
0 ignored issues
show
Bug introduced by
It seems like seeIncludesContainResourceOfType() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

234
            ->/** @scrutinizer ignore-call */ seeIncludesContainResourceOfType(OrdersRestApiConfig::RESOURCE_ORDERS);
Loading history...
235
236
        $ordersAttributes = $this->getDataFromResponseByJsonPath(
237
            sprintf('$.included[?(@.type == %1$s)].attributes', json_encode(OrdersRestApiConfig::RESOURCE_ORDERS)),
238
        );
239
240
        $this->assertNotNull($ordersAttributes);
241
        $this->assertCount(1, $ordersAttributes);
242
        $restOrdersDetailsAttributesTransfer = (new RestOrderDetailsAttributesTransfer())->fromArray($ordersAttributes[0], true);
243
        $this->assertCount(1, $restOrdersDetailsAttributesTransfer->getExpenses());
244
245
        /** @var \Generated\Shared\Transfer\RestOrderExpensesAttributesTransfer $restOrderExpensesAttributesTransfer */
246
        $restOrderExpensesAttributesTransfer = $restOrdersDetailsAttributesTransfer->getExpenses()->getIterator()->current();
247
        $this->assertSame(ShipmentConfig::SHIPMENT_EXPENSE_TYPE, $restOrderExpensesAttributesTransfer->getType());
248
        $this->assertSame($price, $restOrderExpensesAttributesTransfer->getSumPrice());
249
    }
250
251
    /**
252
     * @param array<string> $includes
253
     *
254
     * @return string
255
     */
256
    public function buildCheckoutUrl(array $includes = []): string
257
    {
258
        return $this->formatFullUrl(
259
            '{resourceCheckout}' . $this->formatQueryInclude($includes),
260
            [
261
                'resourceCheckout' => CheckoutRestApiConfig::RESOURCE_CHECKOUT,
262
            ],
263
        );
264
    }
265
266
    /**
267
     * @param array<string> $includes
268
     *
269
     * @return string
270
     */
271
    public function buildCheckoutDataUrl(array $includes = []): string
272
    {
273
        return $this->formatFullUrl(
274
            '{resourceCheckoutData}' . $this->formatQueryInclude($includes),
275
            [
276
                'resourceCheckoutData' => CheckoutRestApiConfig::RESOURCE_CHECKOUT_DATA,
277
            ],
278
        );
279
    }
280
281
    /**
282
     * @return \Spryker\Zed\Store\Business\StoreFacadeInterface
283
     */
284
    public function getStoreFacade(): StoreFacadeInterface
285
    {
286
        return $this->getLocator()
287
            ->store()
288
            ->facade();
289
    }
290
291
    /**
292
     * @return \Spryker\Zed\Customer\Business\CustomerFacadeInterface
293
     */
294
    public function getCustomerFacade(): CustomerFacadeInterface
295
    {
296
        return $this->getLocator()
297
            ->customer()
298
            ->facade();
299
    }
300
301
    /**
302
     * @return \Spryker\Zed\Cart\Business\CartFacadeInterface
303
     */
304
    public function getCartFacade(): CartFacadeInterface
305
    {
306
        return $this->getLocator()->cart()->facade();
307
    }
308
309
    /**
310
     * @param \Generated\Shared\Transfer\AddressTransfer $addressTransfer
311
     *
312
     * @return array
313
     */
314
    public function getAddressRequestPayload(AddressTransfer $addressTransfer): array
315
    {
316
        return [
317
            RestAddressTransfer::SALUTATION => $addressTransfer->getSalutation(),
318
            RestAddressTransfer::FIRST_NAME => $addressTransfer->getFirstName(),
319
            RestAddressTransfer::LAST_NAME => $addressTransfer->getLastName(),
320
            RestAddressTransfer::ADDRESS1 => $addressTransfer->getAddress1(),
321
            RestAddressTransfer::ADDRESS2 => $addressTransfer->getAddress2(),
322
            RestAddressTransfer::ADDRESS3 => $addressTransfer->getAddress3(),
323
            RestAddressTransfer::ZIP_CODE => $addressTransfer->getZipCode(),
324
            RestAddressTransfer::CITY => $addressTransfer->getCity(),
325
            RestAddressTransfer::ISO2_CODE => $addressTransfer->getIso2Code(),
326
            RestAddressTransfer::PHONE => $addressTransfer->getPhone(),
327
            RestCustomerTransfer::EMAIL => $addressTransfer->getEmail(),
328
            RestAddressTransfer::IS_DEFAULT_BILLING => $addressTransfer->getIsDefaultBilling(),
329
            RestAddressTransfer::IS_DEFAULT_SHIPPING => $addressTransfer->getIsDefaultShipping(),
330
        ];
331
    }
332
333
    /**
334
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
335
     *
336
     * @return array
337
     */
338
    public function getCustomerRequestPayload(CustomerTransfer $customerTransfer): array
339
    {
340
        return [
341
            RestCustomerTransfer::SALUTATION => $customerTransfer->getSalutation(),
342
            RestCustomerTransfer::FIRST_NAME => $customerTransfer->getFirstName(),
343
            RestCustomerTransfer::LAST_NAME => $customerTransfer->getLastName(),
344
            RestCustomerTransfer::EMAIL => $customerTransfer->getEmail(),
345
        ];
346
    }
347
348
    /**
349
     * @param string $paymentMethodName
350
     * @param string $paymentProviderName
351
     *
352
     * @return array
353
     */
354
    public function getPaymentRequestPayload(
355
        string $paymentMethodName = self::REQUEST_PARAM_PAYMENT_METHOD_NAME_INVOICE,
356
        string $paymentProviderName = self::REQUEST_PARAM_PAYMENT_PROVIDER_NAME_DUMMY_PAYMENT,
357
    ): array {
358
        return [
359
            [
360
                RestPaymentTransfer::PAYMENT_METHOD_NAME => $paymentMethodName,
361
                RestPaymentTransfer::PAYMENT_PROVIDER_NAME => $paymentProviderName,
362
            ],
363
        ];
364
    }
365
366
    /**
367
     * @param int $idShipmentMethod
368
     *
369
     * @return array
370
     */
371
    public function getShipmentRequestPayload(int $idShipmentMethod): array
372
    {
373
        return [
374
            RestShipmentTransfer::ID_SHIPMENT_METHOD => $idShipmentMethod,
375
        ];
376
    }
377
378
    /**
379
     * @param string $idServicePoint
380
     * @param list<string> $itemGroupKeys
381
     *
382
     * @return list<array<string, mixed>>
383
     */
384
    public function getServicePointsRequestPayload(string $idServicePoint, array $itemGroupKeys): array
385
    {
386
        return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array(array(Gener...EMS => $itemGroupKeys)) returns the type array<integer,array<mixed,array|string>> which is incompatible with the documented return type PyzTest\Glue\Checkout\list.
Loading history...
387
            [
388
                RestServicePointTransfer::ID_SERVICE_POINT => $idServicePoint,
389
                RestServicePointTransfer::ITEMS => $itemGroupKeys,
390
            ],
391
        ];
392
    }
393
394
    /**
395
     * @param \Generated\Shared\Transfer\ItemTransfer $itemTransfer
396
     * @param \Generated\Shared\Transfer\AddressTransfer|null $addressTransfer
397
     *
398
     * @return array<string, mixed>
399
     */
400
    public function getSplitShipmentRequestPayload(ItemTransfer $itemTransfer, ?AddressTransfer $addressTransfer = null): array
401
    {
402
        $shippingAddressPayload = $addressTransfer
403
            ? [RestAddressTransfer::ID => $addressTransfer->getUuidOrFail()]
404
            : $this->getAddressRequestPayload($itemTransfer->getShipmentOrFail()->getShippingAddressOrFail());
405
406
        return [
407
            RestShipmentsTransfer::ID_SHIPMENT_METHOD => $itemTransfer->getShipmentOrFail()->getMethodOrFail()->getIdShipmentMethodOrFail(),
408
            RestShipmentsTransfer::ITEMS => [$itemTransfer->getGroupKeyOrFail()],
409
            RestShipmentsTransfer::SHIPPING_ADDRESS => $shippingAddressPayload,
410
            RestShipmentsTransfer::REQUESTED_DELIVERY_DATE => (new DateTime('tomorrow'))->format('Y-m-d'),
411
        ];
412
    }
413
414
    /**
415
     * @param \Generated\Shared\Transfer\ProductConcreteTransfer $productConcreteTransfer
416
     * @param \Generated\Shared\Transfer\ShipmentMethodTransfer $shipmentMethodTransfer
417
     * @param int $quantity
418
     *
419
     * @return array
420
     */
421
    public function getQuoteItemOverrideData(
422
        ProductConcreteTransfer $productConcreteTransfer,
423
        ShipmentMethodTransfer $shipmentMethodTransfer,
424
        int $quantity = self::DEFAULT_QUOTE_ITEM_QUANTITY,
425
    ): array {
426
        return [
427
            static::QUOTE_ITEM_OVERRIDE_DATA_PRODUCT => $productConcreteTransfer,
428
            static::QUOTE_ITEM_OVERRIDE_DATA_SHIPMENT => [
429
                ShipmentTransfer::METHOD => $shipmentMethodTransfer,
430
            ],
431
            static::QUOTE_ITEM_OVERRIDE_DATA_QUANTITY => $quantity,
432
        ];
433
    }
434
435
    /**
436
     * @param \Generated\Shared\Transfer\ProductOfferTransfer $productOfferTransfer
437
     * @param \Generated\Shared\Transfer\ShipmentMethodTransfer $shipmentMethodTransfer
438
     * @param int $quantity
439
     *
440
     * @return array<string, mixed>
441
     */
442
    public function getQuoteProductOfferItemOverrideData(
443
        ProductOfferTransfer $productOfferTransfer,
444
        ShipmentMethodTransfer $shipmentMethodTransfer,
445
        int $quantity = self::DEFAULT_QUOTE_ITEM_QUANTITY,
446
    ): array {
447
        return [
448
            static::QUOTE_ITEM_OVERRIDE_DATA_PRODUCT_OFFER => $productOfferTransfer,
449
            static::QUOTE_ITEM_OVERRIDE_DATA_SHIPMENT => [
450
                ShipmentTransfer::METHOD => $shipmentMethodTransfer,
451
            ],
452
            static::QUOTE_ITEM_OVERRIDE_DATA_QUANTITY => $quantity,
453
        ];
454
    }
455
456
    /**
457
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
458
     *
459
     * @return void
460
     */
461
    public function authorizeCustomerToGlue(CustomerTransfer $customerTransfer): void
462
    {
463
        $oauthResponseTransfer = $this->haveAuthorizationToGlue($customerTransfer);
464
        $this->amBearerAuthenticated($oauthResponseTransfer->getAccessToken());
465
    }
466
467
    /**
468
     * @return string
469
     */
470
    public function createGuestCustomerReference(): string
471
    {
472
        return uniqid('testReference', true);
473
    }
474
475
    /**
476
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
477
     * @param array<\Generated\Shared\Transfer\ProductOfferTransfer> $productOfferTransfers
478
     * @param array<string, mixed> $overrideShipment
479
     *
480
     * @return \Generated\Shared\Transfer\QuoteTransfer
481
     */
482
    public function havePersistentQuoteWithProductOfferItems(
483
        CustomerTransfer $customerTransfer,
484
        array $productOfferTransfers,
485
        array $overrideShipment = [],
486
    ): QuoteTransfer {
487
        $shipmentTransfer = (new ShipmentBuilder($overrideShipment))
488
            ->withMethod()
489
            ->withShippingAddress()
490
            ->build();
491
492
        return $this->havePersistentQuote([
493
            QuoteTransfer::CUSTOMER => $customerTransfer,
494
            QuoteTransfer::TOTALS => (new TotalsTransfer())
495
                ->setSubtotal(random_int(1000, 10000))
496
                ->setPriceToPay(random_int(1000, 10000)),
497
            QuoteTransfer::ITEMS => $this->mapProductOfferTransfersToQuoteTransferItems($productOfferTransfers),
498
            QuoteTransfer::STORE => [StoreTransfer::NAME => static::TEST_STORE_NAME],
499
            QuoteTransfer::PRICE_MODE => PriceConfig::PRICE_MODE_GROSS,
500
            QuoteTransfer::BILLING_ADDRESS => (new AddressBuilder())->build(),
501
            QuoteTransfer::SHIPMENT => $shipmentTransfer,
502
        ]);
503
    }
504
505
    /**
506
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
507
     * @param array $overrideItems
508
     * @param string $priceMode
509
     *
510
     * @return \Generated\Shared\Transfer\QuoteTransfer
511
     */
512
    public function havePersistentQuoteWithItemsAndItemLevelShipment(
513
        CustomerTransfer $customerTransfer,
514
        array $overrideItems = [],
515
        string $priceMode = PriceConfig::PRICE_MODE_GROSS,
516
    ): QuoteTransfer {
517
        return $this->havePersistentQuote([
518
            QuoteTransfer::CUSTOMER => $customerTransfer,
519
            QuoteTransfer::TOTALS => (new TotalsTransfer())
520
                ->setSubtotal(random_int(1000, 10000))
521
                ->setPriceToPay(random_int(1000, 10000)),
522
            QuoteTransfer::ITEMS => $this->mapProductConcreteTransfersToQuoteTransferItemsWithItemLevelShipment($overrideItems),
523
            QuoteTransfer::STORE => [StoreTransfer::NAME => 'DE'],
524
            QuoteTransfer::PRICE_MODE => $priceMode,
525
            QuoteTransfer::BILLING_ADDRESS => (new AddressBuilder())->build(),
526
        ]);
527
    }
528
529
    /**
530
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
531
     * @param array<string, mixed> $overrideItemsData
532
     * @param string $priceMode
533
     *
534
     * @return \Generated\Shared\Transfer\QuoteTransfer
535
     */
536
    public function havePersistentQuoteWithProductOfferItemsAndItemLevelShipment(
537
        CustomerTransfer $customerTransfer,
538
        array $overrideItemsData,
539
        string $priceMode = PriceConfig::PRICE_MODE_GROSS,
540
    ): QuoteTransfer {
541
        return $this->havePersistentQuote([
542
            QuoteTransfer::CUSTOMER => $customerTransfer,
543
            QuoteTransfer::TOTALS => (new TotalsTransfer())
544
                ->setSubtotal(random_int(1000, 10000))
545
                ->setPriceToPay(random_int(1000, 10000)),
546
            QuoteTransfer::ITEMS => $this->mapProductOfferTransfersToQuoteTransferItemsWithItemLevelShipment($overrideItemsData),
547
            QuoteTransfer::STORE => [StoreTransfer::NAME => static::TEST_STORE_NAME],
548
            QuoteTransfer::PRICE_MODE => $priceMode,
549
            QuoteTransfer::BILLING_ADDRESS => (new AddressBuilder())->build(),
550
        ]);
551
    }
552
553
    /**
554
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
555
     *
556
     * @return \Generated\Shared\Transfer\QuoteTransfer
557
     */
558
    public function havePersistentQuoteWithItemAndItemServicePoint(CustomerTransfer $customerTransfer): QuoteTransfer
559
    {
560
        $productConcreteTransfer = $this->haveProductWithStock();
561
        $storeTransfer = $this->haveStore([StoreTransfer::NAME => static::TEST_STORE_NAME]);
562
        $quoteItemData = $this->createItemTransferWithServicePoint($productConcreteTransfer, $storeTransfer)->toArray();
563
564
        return $this->havePersistentQuote([
565
            QuoteTransfer::CUSTOMER => $customerTransfer,
566
            QuoteTransfer::TOTALS => (new TotalsTransfer())
567
                ->setSubtotal(random_int(1000, 10000))
568
                ->setPriceToPay(random_int(1000, 10000)),
569
            QuoteTransfer::ITEMS => [$quoteItemData],
570
            QuoteTransfer::STORE => $storeTransfer->toArray(),
571
            QuoteTransfer::PRICE_MODE => PriceConfig::PRICE_MODE_GROSS,
572
        ]);
573
    }
574
575
    /**
576
     * @param array $overrideCustomer
577
     *
578
     * @return \Generated\Shared\Transfer\QuoteTransfer
579
     */
580
    public function haveEmptyPersistentQuote(array $overrideCustomer = []): QuoteTransfer
581
    {
582
        return $this->havePersistentQuote([
583
            QuoteTransfer::CUSTOMER => (new CustomerBuilder($overrideCustomer))->build(),
584
            QuoteTransfer::BILLING_ADDRESS => (new AddressBuilder())->build(),
585
        ]);
586
    }
587
588
    /**
589
     * @return \Generated\Shared\Transfer\ProductConcreteTransfer
590
     */
591
    public function haveProductWithStock(): ProductConcreteTransfer
592
    {
593
        $productConcreteTransfer = $this->haveFullProduct();
594
595
        $this->haveProductInStockForStore($this->getStoreFacade()->getCurrentStore(), [
596
            StockProductTransfer::SKU => $productConcreteTransfer->getSku(),
597
            StockProductTransfer::IS_NEVER_OUT_OF_STOCK => 1,
598
        ]);
599
600
        $priceProductOverride = [
601
            PriceProductTransfer::SKU_PRODUCT_ABSTRACT => $productConcreteTransfer->getAbstractSku(),
602
            PriceProductTransfer::SKU_PRODUCT => $productConcreteTransfer->getSku(),
603
            PriceProductTransfer::ID_PRODUCT => $productConcreteTransfer->getIdProductConcrete(),
604
            PriceProductTransfer::PRICE_TYPE_NAME => 'DEFAULT',
605
            PriceProductTransfer::MONEY_VALUE => [
606
                MoneyValueTransfer::NET_AMOUNT => 770,
607
                MoneyValueTransfer::GROSS_AMOUNT => 880,
608
            ],
609
        ];
610
        $this->havePriceProduct($priceProductOverride);
611
612
        return $productConcreteTransfer;
613
    }
614
615
    /**
616
     * @param \Generated\Shared\Transfer\ProductConcreteTransfer $productConcreteTransfer
617
     * @param \Generated\Shared\Transfer\ServiceTransfer $serviceTransfer
618
     * @param \Generated\Shared\Transfer\ShipmentTypeTransfer $shipmentTypeTransfer
619
     * @param array<string, mixed> $override
620
     *
621
     * @return \Generated\Shared\Transfer\ProductOfferTransfer
622
     */
623
    public function haveProductOfferWithShipmentTypeAndServiceRelations(
624
        ProductConcreteTransfer $productConcreteTransfer,
625
        ServiceTransfer $serviceTransfer,
626
        ShipmentTypeTransfer $shipmentTypeTransfer,
627
        array $override = [],
628
    ): ProductOfferTransfer {
629
        $productOfferTransfer = $this->haveProductOfferWithStock($productConcreteTransfer, $override);
630
        $this->haveProductOfferService([
631
            ProductOfferServiceTransfer::ID_PRODUCT_OFFER => $productOfferTransfer->getIdProductOffer(),
632
            ProductOfferServiceTransfer::ID_SERVICE => $serviceTransfer->getIdServiceOrFail(),
633
        ]);
634
        $this->haveProductOfferShipmentType($productOfferTransfer, $shipmentTypeTransfer);
635
636
        return $productOfferTransfer;
637
    }
638
639
    /**
640
     * @param \Generated\Shared\Transfer\ProductConcreteTransfer $productConcreteTransfer
641
     * @param array<string, mixed> $override
642
     *
643
     * @return \Generated\Shared\Transfer\ProductOfferTransfer
644
     */
645
    public function haveProductOfferWithStock(ProductConcreteTransfer $productConcreteTransfer, array $override = []): ProductOfferTransfer
646
    {
647
        $override[ProductOfferTransfer::CONCRETE_SKU] = $productConcreteTransfer->getSkuOrFail();
648
        $override[ProductOfferTransfer::ID_PRODUCT_CONCRETE] = $productConcreteTransfer->getIdProductConcreteOrFail();
649
        $override[ProductOfferTransfer::ID_PRODUCT_ABSTRACT] = $productConcreteTransfer->getFkProductAbstractOrFail();
650
651
        if (!isset($override[ProductOfferTransfer::MERCHANT_REFERENCE])) {
652
            $merchantTransfer = $this->haveMerchant([
653
                MerchantTransfer::IS_ACTIVE => true,
654
                MerchantTransfer::STATUS => static::MERCHANT_STATUS_APPROVED,
655
                MerchantTransfer::MERCHANT_PROFILE => new MerchantProfileTransfer(),
656
            ]);
657
658
            $override[ProductOfferTransfer::MERCHANT_REFERENCE] = $merchantTransfer->getMerchantReferenceOrFail();
659
        }
660
661
        $productOfferTransfer = $this->haveProductOffer($override);
662
663
        $this->haveProductOfferStock([
664
            ProductOfferStockTransfer::ID_PRODUCT_OFFER => $productOfferTransfer->getIdProductOfferOrFail(),
665
            ProductOfferStockTransfer::QUANTITY => $override[ProductOfferStockTransfer::QUANTITY] ?? 0,
666
            ProductOfferStockTransfer::IS_NEVER_OUT_OF_STOCK => $override[ProductOfferStockTransfer::IS_NEVER_OUT_OF_STOCK] ?? true,
667
            ProductOfferStockTransfer::STOCK => $override[ProductOfferStockTransfer::STOCK] ?? null,
668
        ]);
669
670
        return $productOfferTransfer;
671
    }
672
673
    /**
674
     * @param array $override
675
     *
676
     * @return \Generated\Shared\Transfer\CustomerTransfer
677
     */
678
    public function createCustomerTransfer(array $override = []): CustomerTransfer
679
    {
680
        return (new CustomerBuilder($override))->build();
681
    }
682
683
    /**
684
     * @param array $override
685
     *
686
     * @return \Generated\Shared\Transfer\CustomerTransfer
687
     */
688
    public function haveCustomerWithPersistentAddress(array $override = []): CustomerTransfer
689
    {
690
        $customerTransfer = $this->haveCustomer($override);
691
692
        return $this->haveAddressForCustomer($customerTransfer);
693
    }
694
695
    /**
696
     * @param array $paymentMethodOverrideData
697
     * @param array $storeOverrideData
698
     *
699
     * @return \Generated\Shared\Transfer\PaymentMethodTransfer
700
     */
701
    public function havePaymentMethodWithStore(
702
        array $paymentMethodOverrideData = [],
703
        array $storeOverrideData = [
704
            StoreTransfer::NAME => 'DE',
705
            StoreTransfer::DEFAULT_CURRENCY_ISO_CODE => 'EUR',
706
            StoreTransfer::AVAILABLE_CURRENCY_ISO_CODES => ['EUR'],
707
        ],
708
    ): PaymentMethodTransfer {
709
        $storeTransfer = $this->haveStore($storeOverrideData);
710
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
711
            StoreRelationTransfer::ID_STORES => [
712
                $storeTransfer->getIdStore(),
713
            ],
714
            StoreRelationTransfer::STORES => [
715
                $storeTransfer,
716
            ],
717
        ])->build();
718
719
        $paymentMethodOverrideData = array_merge($paymentMethodOverrideData, [PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer]);
720
721
        return $this->havePaymentMethod($paymentMethodOverrideData);
722
    }
723
724
    /**
725
     * @param \Generated\Shared\Transfer\MerchantTransfer $merchantTransfer
726
     * @param \Generated\Shared\Transfer\ProductConcreteTransfer $productConcreteTransfer
727
     *
728
     * @return \Generated\Shared\Transfer\ProductOfferTransfer
729
     */
730
    public function createProductOfferWithStock(
731
        MerchantTransfer $merchantTransfer,
732
        ProductConcreteTransfer $productConcreteTransfer,
733
    ): ProductOfferTransfer {
734
        $storeTransfer = $this->getStoreFacade()->getCurrentStore();
735
736
        $productOfferTransfer = $this->haveProductOffer([
737
            ProductOfferTransfer::CONCRETE_SKU => $productConcreteTransfer->getSkuOrFail(),
738
            ProductOfferTransfer::ID_PRODUCT_CONCRETE => $productConcreteTransfer->getIdProductConcreteOrFail(),
739
            ProductOfferTransfer::STORES => new ArrayObject([$storeTransfer]),
740
            ProductOfferTransfer::MERCHANT_REFERENCE => $merchantTransfer->getMerchantReferenceOrFail(),
741
        ]);
742
743
        $productOfferStockTransfer = $this->haveProductOfferStock([
744
            ProductOfferStockTransfer::ID_PRODUCT_OFFER => $productOfferTransfer->getIdProductOfferOrFail(),
745
            ProductOfferStockTransfer::QUANTITY => 1,
746
            ProductOfferStockTransfer::IS_NEVER_OUT_OF_STOCK => 1,
747
            ProductOfferStockTransfer::STOCK => [
748
                StockTransfer::STORE_RELATION => [
749
                    StoreRelationTransfer::ID_STORES => [$storeTransfer->getIdStore()],
750
                ],
751
            ],
752
        ]);
753
754
        $this->updateStock($productOfferStockTransfer->getStock()->setIsActive(true));
755
756
        $this->havePriceProductOffer([
757
            PriceProductOfferTransfer::FK_PRODUCT_OFFER => $productOfferTransfer->getIdProductOfferOrFail(),
758
            PriceProductTransfer::SKU_PRODUCT => $productConcreteTransfer->getSkuOrFail(),
759
            PriceProductTransfer::SKU_PRODUCT_ABSTRACT => $productConcreteTransfer->getAbstractSkuOrFail(),
760
            PriceProductTransfer::PRICE_TYPE_NAME => 'DEFAULT',
761
            PriceProductTransfer::MONEY_VALUE => [
762
                MoneyValueTransfer::NET_AMOUNT => 770,
763
                MoneyValueTransfer::GROSS_AMOUNT => 880,
764
            ],
765
        ]);
766
767
        return $productOfferTransfer;
768
    }
769
770
    /**
771
     * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer
772
     *
773
     * @return \Generated\Shared\Transfer\ShipmentTypeTransfer
774
     */
775
    public function havePickableShipmentType(StoreTransfer $storeTransfer): ShipmentTypeTransfer
776
    {
777
        $shipmentTypeEntity = SpyShipmentTypeQuery::create()
778
            ->filterByKey(static::SHIPMENT_TYPE_KEY_PICKUP)
779
            ->findOne();
780
781
        if ($shipmentTypeEntity !== null) {
782
            return (new ShipmentTypeTransfer())->fromArray($shipmentTypeEntity->toArray());
783
        }
784
785
        return $this->haveShipmentType([
786
            ShipmentTypeTransfer::IS_ACTIVE => true,
787
            ShipmentTypeTransfer::KEY => static::SHIPMENT_TYPE_KEY_PICKUP,
788
            ShipmentTypeTransfer::STORE_RELATION => (new StoreRelationTransfer())->addStores($storeTransfer),
789
        ]);
790
    }
791
792
    /**
793
     * @param \Generated\Shared\Transfer\ShipmentTypeTransfer $shipmentTypeTransfer
794
     * @param array<string, mixed> $seedData
795
     *
796
     * @return \Generated\Shared\Transfer\ServiceTransfer
797
     */
798
    public function havePickableService(ShipmentTypeTransfer $shipmentTypeTransfer, array $seedData = []): ServiceTransfer
799
    {
800
        $shipmentServiceTypeEntity = $this->getSpyShipmentTypeServiceTypeQuery()
801
            ->filterByFkShipmentType($shipmentTypeTransfer->getIdShipmentTypeOrFail())
802
            ->findOne();
803
        if ($shipmentServiceTypeEntity !== null) {
804
            $serviceTypeEntity = $this->getServiceTypeQuery()
805
                ->findOneByIdServiceType($shipmentServiceTypeEntity->getFkServiceType());
806
            $serviceTypeTransfer = (new ServiceTypeTransfer())->fromArray($serviceTypeEntity->toArray(), true);
807
            $seedData[ServiceTransfer::SERVICE_TYPE] = $serviceTypeTransfer->toArray();
808
        }
809
810
        $serviceTransfer = $this->haveService($seedData);
811
        $this->haveShipmentTypeServiceTypeRelation($shipmentTypeTransfer, $serviceTransfer->getServiceTypeOrFail());
812
813
        return $serviceTransfer;
814
    }
815
816
    /**
817
     * @param \Generated\Shared\Transfer\ShipmentMethodTransfer $shipmentMethodTransfer
818
     * @param \Generated\Shared\Transfer\ShipmentTypeTransfer $shipmentTypeTransfer
819
     *
820
     * @return void
821
     */
822
    public function addShipmentTypeToShipmentMethod(
823
        ShipmentMethodTransfer $shipmentMethodTransfer,
824
        ShipmentTypeTransfer $shipmentTypeTransfer,
825
    ): void {
826
        /** @var \Orm\Zed\Shipment\Persistence\SpyShipmentMethod $shipmentMethodEntity */
827
        $shipmentMethodEntity = (SpyShipmentMethodQuery::create())
828
            ->findOneByIdShipmentMethod($shipmentMethodTransfer->getIdShipmentMethodOrFail());
829
830
        $shipmentMethodEntity->setFkShipmentType($shipmentTypeTransfer->getIdShipmentTypeOrFail());
831
        $shipmentMethodEntity->save();
832
    }
833
834
    /**
835
     * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer
836
     *
837
     * @return \Generated\Shared\Transfer\ServicePointTransfer
838
     */
839
    public function haveServicePointWithoutAddress(StoreTransfer $storeTransfer): ServicePointTransfer
840
    {
841
        $servicePointBuilder = (new ServicePointBuilder([
842
            ServicePointTransfer::UUID => uniqid('test-service-point'),
843
            ServicePointTransfer::KEY => uniqid('test-service-point'),
844
            ServicePointTransfer::IS_ACTIVE => true,
845
        ]))
846
            ->withStoreRelation([
847
                StoreRelationTransfer::STORES =>
848
                    [
849
                        $storeTransfer->toArray(),
850
                    ],
851
            ])
852
            ->build();
853
854
        return $this->haveServicePoint($servicePointBuilder->toArray());
855
    }
856
857
    /**
858
     * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer
859
     *
860
     * @return \Generated\Shared\Transfer\ServicePointTransfer
861
     */
862
    public function haveServicePointWithAddress(StoreTransfer $storeTransfer): ServicePointTransfer
863
    {
864
        $countryTransfer = $this->haveCountryTransfer([
865
            CountryTransfer::ISO2_CODE => static::COUNTRY_ISO2_CODE,
866
            CountryTransfer::ISO3_CODE => static::COUNTRY_ISO3_CODE,
867
        ]);
868
        $servicePointTransfer = $this->haveServicePoint([
869
            ServicePointTransfer::IS_ACTIVE => true,
870
            ServicePointTransfer::STORE_RELATION => (new StoreRelationTransfer())->addStores($storeTransfer),
871
        ]);
872
        $servicePointAddressTransfer = $this->haveServicePointAddress([
873
            ServicePointAddressTransfer::SERVICE_POINT => $servicePointTransfer,
874
            ServicePointAddressTransfer::COUNTRY => $countryTransfer,
875
        ]);
876
877
        return $servicePointTransfer->setAddress($servicePointAddressTransfer->setServicePoint(null));
878
    }
879
880
    /**
881
     * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer
882
     *
883
     * @return \Generated\Shared\Transfer\MerchantTransfer
884
     */
885
    public function haveMerchantWithStoreRelation(StoreTransfer $storeTransfer): MerchantTransfer
886
    {
887
        $merchantTransfer = (new MerchantBuilder([
888
            MerchantTransfer::STATUS => static::MERCHANT_STATUS_APPROVED,
889
            MerchantTransfer::IS_ACTIVE => true,
890
            MerchantTransfer::STORE_RELATION => (new StoreRelationTransfer())
891
                ->addIdStores($storeTransfer->getIdStoreOrFail())
892
                ->addStores($storeTransfer),
893
        ]))->withMerchantProfile()->build();
894
895
        return $this->haveMerchant($merchantTransfer->toArray(true, true));
896
    }
897
898
    /**
899
     * @param \Generated\Shared\Transfer\AddressTransfer $addressTransfer
900
     *
901
     * @return void
902
     */
903
    public function assertCustomerBillingAddressInOrders(AddressTransfer $addressTransfer): void
904
    {
905
        $jsonPath = sprintf('$..included[?(@.type == \'%s\')]', 'orders');
906
        $billingAddress = $this->getDataFromResponseByJsonPath($jsonPath)[0]['attributes']['billingAddress'];
907
908
        $this->assertSame($addressTransfer->getAddress1(), $billingAddress['address1']);
909
        $this->assertSame($addressTransfer->getAddress2(), $billingAddress['address2']);
910
        $this->assertSame($addressTransfer->getAddress3(), $billingAddress['address3']);
911
        $this->assertSame($addressTransfer->getCompany(), $billingAddress['company']);
912
        $this->assertSame($addressTransfer->getCity(), $billingAddress['city']);
913
        $this->assertSame($addressTransfer->getZipCode(), $billingAddress['zipCode']);
914
        $this->assertSame($addressTransfer->getIso2Code(), $billingAddress['iso2Code']);
915
    }
916
917
    /**
918
     * @param \Generated\Shared\Transfer\AddressTransfer $addressTransfer
919
     *
920
     * @return void
921
     */
922
    public function assertCustomerShippingAddressInOrderShipments(
923
        AddressTransfer $addressTransfer,
924
    ): void {
925
        $jsonPath = sprintf('$..included[?(@.type == \'%s\')]', 'order-shipments');
926
        $shippingAddress = $this->getDataFromResponseByJsonPath($jsonPath)[0]['attributes']['shippingAddress'];
927
928
        $this->assertSame($addressTransfer->getAddress1(), $shippingAddress['address1']);
929
        $this->assertSame($addressTransfer->getAddress2(), $shippingAddress['address2']);
930
        $this->assertSame($addressTransfer->getAddress3(), $shippingAddress['address3']);
931
        $this->assertSame($addressTransfer->getCompany(), $shippingAddress['company']);
932
        $this->assertSame($addressTransfer->getCity(), $shippingAddress['city']);
933
        $this->assertSame($addressTransfer->getZipCode(), $shippingAddress['zipCode']);
934
        $this->assertSame($addressTransfer->getIso2Code(), $shippingAddress['iso2Code']);
935
    }
936
937
    /**
938
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
939
     *
940
     * @return \Generated\Shared\Transfer\CustomerTransfer
941
     */
942
    protected function haveAddressForCustomer(CustomerTransfer $customerTransfer): CustomerTransfer
943
    {
944
        $addressTransfer = (new AddressBuilder([
945
            AddressTransfer::EMAIL => $customerTransfer->getEmail(),
946
            AddressTransfer::FK_CUSTOMER => $customerTransfer->getIdCustomer(),
947
            AddressTransfer::FIRST_NAME => $customerTransfer->getFirstName(),
948
            AddressTransfer::LAST_NAME => $customerTransfer->getLastName(),
949
        ]))->build();
950
        $customerFacade = $this->getCustomerFacade();
951
        $customerFacade->createAddress($addressTransfer);
952
953
        return $customerFacade->getCustomer($customerTransfer);
954
    }
955
956
    /**
957
     * @param array<\Generated\Shared\Transfer\ProductOfferTransfer> $productOfferTransfers
958
     *
959
     * @return array
960
     */
961
    protected function mapProductOfferTransfersToQuoteTransferItems(array $productOfferTransfers): array
962
    {
963
        $quoteTransferItems = [];
964
965
        foreach ($productOfferTransfers as $productOfferTransfer) {
966
            $quoteTransferItems[] = (new ItemBuilder([
967
                ItemTransfer::SKU => $productOfferTransfer->getConcreteSkuOrFail(),
968
                ItemTransfer::GROUP_KEY => $productOfferTransfer->getConcreteSkuOrFail(),
969
                ItemTransfer::ID_PRODUCT_ABSTRACT => $productOfferTransfer->getIdProductAbstractOrFail(),
970
                ItemTransfer::PRODUCT_OFFER_REFERENCE => $productOfferTransfer->getProductOfferReferenceOrFail(),
971
                ItemTransfer::MERCHANT_REFERENCE => $productOfferTransfer->getMerchantReference(),
972
                ItemTransfer::QUANTITY => static::DEFAULT_QUOTE_ITEM_QUANTITY,
973
            ]))->build()->modifiedToArray();
974
        }
975
976
        return $quoteTransferItems;
977
    }
978
979
    /**
980
     * @param array $overrideItems
981
     *
982
     * @return array
983
     */
984
    protected function mapProductConcreteTransfersToQuoteTransferItemsWithItemLevelShipment(array $overrideItems = []): array
985
    {
986
        $quoteTransferItems = [];
987
988
        foreach ($overrideItems as $overrideItem) {
989
            $productConcreteTransfer = $this->getProductConcreteTransferFromOverrideItemData($overrideItem);
990
            $overrideShipment = $this->getOverrideShipmentDataFromOverrideItemData($overrideItem);
991
            /** @var \Generated\Shared\Transfer\ProductOfferTransfer|null $productOfferTransfer */
992
            $productOfferTransfer = $productConcreteTransfer->getOffers()->getIterator()->current();
993
994
            $quoteTransferItems[] = (new ItemBuilder([
995
                ItemTransfer::SKU => $productConcreteTransfer->getSku(),
996
                ItemTransfer::GROUP_KEY => $productConcreteTransfer->getSku(),
997
                ItemTransfer::ABSTRACT_SKU => $productConcreteTransfer->getAbstractSku(),
998
                ItemTransfer::ID_PRODUCT_ABSTRACT => $productConcreteTransfer->getFkProductAbstract(),
999
                ItemTransfer::QUANTITY => $this->getQuoteItemQuantityFromOverrideItemData($overrideItem),
1000
                ItemTransfer::PRODUCT_OFFER_REFERENCE => $productOfferTransfer?->getProductOfferReference(),
1001
                ItemTransfer::MERCHANT_REFERENCE => $productOfferTransfer?->getMerchantReference(),
1002
            ]))->withShipment((new ShipmentBuilder($overrideShipment))
1003
                ->withMethod()
1004
                ->withShippingAddress())
1005
                ->build()
1006
                ->modifiedToArray();
1007
        }
1008
1009
        return $quoteTransferItems;
1010
    }
1011
1012
    /**
1013
     * @param array<string, mixed> $overrideItemsData
1014
     *
1015
     * @return array<string, mixed>
1016
     */
1017
    protected function mapProductOfferTransfersToQuoteTransferItemsWithItemLevelShipment(array $overrideItemsData): array
1018
    {
1019
        $itemTransfersData = [];
1020
        foreach ($overrideItemsData as $overrideItemData) {
1021
            $overrideShipment = $this->getOverrideShipmentDataFromOverrideItemData($overrideItemData);
1022
            $productOfferTransfer = $overrideItemData[static::QUOTE_ITEM_OVERRIDE_DATA_PRODUCT_OFFER];
1023
1024
            $itemTransfersData[] = (new ItemBuilder([
1025
                ItemTransfer::SKU => $productOfferTransfer->getConcreteSkuOrFail(),
1026
                ItemTransfer::GROUP_KEY => $productOfferTransfer->getConcreteSkuOrFail(),
1027
                ItemTransfer::ID_PRODUCT_ABSTRACT => $productOfferTransfer->getIdProductAbstractOrFail(),
1028
                ItemTransfer::PRODUCT_OFFER_REFERENCE => $productOfferTransfer->getProductOfferReferenceOrFail(),
1029
                ItemTransfer::MERCHANT_REFERENCE => $productOfferTransfer->getMerchantReference(),
1030
                ItemTransfer::QUANTITY => $this->getQuoteItemQuantityFromOverrideItemData($overrideItemData),
1031
            ]))->withShipment((new ShipmentBuilder($overrideShipment))
1032
                ->withMethod()
1033
                ->withShippingAddress())
1034
                ->build()
1035
                ->modifiedToArray();
1036
        }
1037
1038
        return $itemTransfersData;
1039
    }
1040
1041
    /**
1042
     * @param \Generated\Shared\Transfer\ProductConcreteTransfer $productConcreteTransfer
1043
     * @param \Generated\Shared\Transfer\StoreTransfer $storeTransfer
1044
     *
1045
     * @return \Generated\Shared\Transfer\ItemTransfer
1046
     */
1047
    protected function createItemTransferWithServicePoint(
1048
        ProductConcreteTransfer $productConcreteTransfer,
1049
        StoreTransfer $storeTransfer,
1050
    ): ItemTransfer {
1051
        $servicePointTransfer = $this->haveServicePointWithAddress($storeTransfer);
1052
1053
        return (new ItemBuilder([
1054
            ItemTransfer::SKU => $productConcreteTransfer->getSku(),
1055
            ItemTransfer::GROUP_KEY => $productConcreteTransfer->getSku(),
1056
            ItemTransfer::ABSTRACT_SKU => $productConcreteTransfer->getAbstractSku(),
1057
            ItemTransfer::ID_PRODUCT_ABSTRACT => $productConcreteTransfer->getFkProductAbstract(),
1058
            ItemTransfer::QUANTITY => 1,
1059
            ItemTransfer::SERVICE_POINT => $servicePointTransfer->toArray(),
1060
        ]))->build();
1061
    }
1062
1063
    /**
1064
     * @param array $overrideItem
1065
     *
1066
     * @return \Generated\Shared\Transfer\ProductConcreteTransfer
1067
     */
1068
    protected function getProductConcreteTransferFromOverrideItemData(array $overrideItem): ProductConcreteTransfer
1069
    {
1070
        return $overrideItem[static::QUOTE_ITEM_OVERRIDE_DATA_PRODUCT];
1071
    }
1072
1073
    /**
1074
     * @param array $overrideItem
1075
     *
1076
     * @return array
1077
     */
1078
    protected function getOverrideShipmentDataFromOverrideItemData(array $overrideItem = []): array
1079
    {
1080
        return $overrideItem[static::QUOTE_ITEM_OVERRIDE_DATA_SHIPMENT];
1081
    }
1082
1083
    /**
1084
     * @param array $overrideItem
1085
     *
1086
     * @return int
1087
     */
1088
    protected function getQuoteItemQuantityFromOverrideItemData(array $overrideItem): int
1089
    {
1090
        return $overrideItem[static::QUOTE_ITEM_OVERRIDE_DATA_QUANTITY] ?? static::DEFAULT_QUOTE_ITEM_QUANTITY;
1091
    }
1092
1093
    /**
1094
     * @param array<string> $includes
1095
     *
1096
     * @return string
1097
     */
1098
    protected function formatQueryInclude(array $includes = []): string
1099
    {
1100
        if (!$includes) {
1101
            return '';
1102
        }
1103
1104
        return sprintf('?%s=%s', RequestConstantsInterface::QUERY_INCLUDE, implode(',', $includes));
1105
    }
1106
1107
    /**
1108
     * @param string $orderReference
1109
     * @param string $itemSku
1110
     *
1111
     * @return \Orm\Zed\Sales\Persistence\SpySalesOrderAddress|null
1112
     */
1113
    protected function findSalesOrderAddressEntity(string $orderReference, string $itemSku): ?SpySalesOrderAddress
1114
    {
1115
        return $this->getSpySalesOrderAddressQuery()
1116
            ->useSpySalesShipmentQuery()
1117
                ->useOrderQuery()
1118
                    ->filterByOrderReference($orderReference)
1119
                ->endUse()
1120
                ->useSpySalesOrderItemQuery()
1121
                    ->filterBySku($itemSku)
1122
                ->endUse()
1123
            ->endUse()
1124
            ->findOne();
1125
    }
1126
1127
    /**
1128
     * @return \Orm\Zed\ShipmentType\Persistence\SpyShipmentTypeQuery
1129
     */
1130
    protected function getShipmentTypeQuery(): SpyShipmentTypeQuery
1131
    {
1132
        return SpyShipmentTypeQuery::create();
1133
    }
1134
1135
    /**
1136
     * @return \Orm\Zed\Sales\Persistence\SpySalesOrderAddressQuery
1137
     */
1138
    protected function getSpySalesOrderAddressQuery(): SpySalesOrderAddressQuery
1139
    {
1140
        return SpySalesOrderAddressQuery::create();
1141
    }
1142
1143
    /**
1144
     * @return \Orm\Zed\ShipmentTypeServicePoint\Persistence\SpyShipmentTypeServiceTypeQuery
1145
     */
1146
    protected function getSpyShipmentTypeServiceTypeQuery(): SpyShipmentTypeServiceTypeQuery
1147
    {
1148
        return SpyShipmentTypeServiceTypeQuery::create();
1149
    }
1150
1151
    /**
1152
     * @return \Orm\Zed\ServicePoint\Persistence\SpyServiceTypeQuery
1153
     */
1154
    protected function getServiceTypeQuery(): SpyServiceTypeQuery
1155
    {
1156
        return SpyServiceTypeQuery::create();
1157
    }
1158
}
1159