Passed
Pull Request — master (#356)
by Denys
05:13
created

CheckoutApiTester   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 637
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 36
eloc 231
dl 0
loc 637
rs 9.52
c 1
b 0
f 0

33 Methods

Rating   Name   Duplication   Size   Complexity  
A buildCheckoutDataUrl() 0 6 1
A assertCustomerShippingAddressInOrderShipments() 0 13 1
A getAddressRequestPayload() 0 16 1
A havePaymentMethodWithStore() 0 21 1
A getCartFacade() 0 3 1
A getCustomerRequestPayload() 0 7 1
A assertCheckoutResponseResourceHasCorrectData() 0 21 1
A assertCheckoutDataResponseResourceHasCorrectData() 0 11 1
A authorizeCustomerToGlue() 0 4 1
A assertShipmentExpensesHaveCorrectPrice() 0 19 1
A haveProductWithStock() 0 22 1
A mapProductConcreteTransfersToQuoteTransferItemsWithItemLevelShipment() 0 26 2
A getSplitShipmentRequestPayload() 0 11 2
A getOverrideShipmentDataFromOverrideItemData() 0 3 1
A createCustomerTransfer() 0 3 1
A haveEmptyPersistentQuote() 0 5 1
A assertCompanyBusinessUnitBillingAddressInOrders() 0 13 1
A getCustomerFacade() 0 5 1
A getShipmentRequestPayload() 0 4 1
A assertCompanyBusinessUnitShippingAddressInOrderShipments() 0 13 1
A getQuoteItemOverrideData() 0 11 1
A assertCustomerBillingAddressInOrders() 0 12 1
A getStoreFacade() 0 5 1
A buildCheckoutUrl() 0 6 1
A haveCustomerWithPersistentAddress() 0 5 1
A haveAddressForCustomer() 0 12 1
A getProductConcreteTransferFromOverrideItemData() 0 3 1
A createProductOfferWithStock() 0 38 1
A getSplitShipmentRequestPayloadWithCompanyBusinessUnitAddress() 0 11 1
A getQuoteItemQuantityFromOverrideItemData() 0 3 1
A getPaymentRequestPayload() 0 8 1
A formatQueryInclude() 0 7 2
A havePersistentQuoteWithItemsAndItemLevelShipment() 0 14 1
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
namespace PyzTest\Glue\Checkout;
9
10
use ArrayObject;
11
use DateTime;
12
use Generated\Shared\DataBuilder\AddressBuilder;
13
use Generated\Shared\DataBuilder\CustomerBuilder;
14
use Generated\Shared\DataBuilder\ItemBuilder;
15
use Generated\Shared\DataBuilder\ShipmentBuilder;
16
use Generated\Shared\DataBuilder\StoreRelationBuilder;
17
use Generated\Shared\Transfer\AddressTransfer;
18
use Generated\Shared\Transfer\CompanyUnitAddressTransfer;
19
use Generated\Shared\Transfer\CustomerTransfer;
20
use Generated\Shared\Transfer\ItemTransfer;
21
use Generated\Shared\Transfer\MerchantTransfer;
22
use Generated\Shared\Transfer\MoneyValueTransfer;
23
use Generated\Shared\Transfer\PaymentMethodTransfer;
24
use Generated\Shared\Transfer\PriceProductOfferTransfer;
25
use Generated\Shared\Transfer\PriceProductTransfer;
26
use Generated\Shared\Transfer\ProductConcreteTransfer;
27
use Generated\Shared\Transfer\ProductOfferStockTransfer;
28
use Generated\Shared\Transfer\ProductOfferTransfer;
29
use Generated\Shared\Transfer\QuoteTransfer;
30
use Generated\Shared\Transfer\RestAddressTransfer;
31
use Generated\Shared\Transfer\RestCheckoutDataTransfer;
32
use Generated\Shared\Transfer\RestCheckoutResponseTransfer;
33
use Generated\Shared\Transfer\RestCustomerTransfer;
34
use Generated\Shared\Transfer\RestOrderDetailsAttributesTransfer;
35
use Generated\Shared\Transfer\RestPaymentTransfer;
36
use Generated\Shared\Transfer\RestShipmentsTransfer;
37
use Generated\Shared\Transfer\RestShipmentTransfer;
38
use Generated\Shared\Transfer\ShipmentMethodTransfer;
39
use Generated\Shared\Transfer\ShipmentTransfer;
40
use Generated\Shared\Transfer\StockProductTransfer;
41
use Generated\Shared\Transfer\StockTransfer;
42
use Generated\Shared\Transfer\StoreRelationTransfer;
43
use Generated\Shared\Transfer\StoreTransfer;
44
use Generated\Shared\Transfer\TotalsTransfer;
45
use Spryker\Glue\CheckoutRestApi\CheckoutRestApiConfig;
46
use Spryker\Glue\GlueApplication\Rest\RequestConstantsInterface;
47
use Spryker\Glue\OrdersRestApi\OrdersRestApiConfig;
48
use Spryker\Shared\Price\PriceConfig;
49
use Spryker\Shared\Shipment\ShipmentConfig;
50
use Spryker\Zed\Cart\Business\CartFacadeInterface;
51
use Spryker\Zed\Customer\Business\CustomerFacadeInterface;
52
use Spryker\Zed\Store\Business\StoreFacadeInterface;
53
use SprykerTest\Glue\Testify\Tester\ApiEndToEndTester;
54
55
/**
56
 * Inherited Methods
57
 *
58
 * @method void wantToTest($text)
59
 * @method void wantTo($text)
60
 * @method void execute($callable)
61
 * @method void expectTo($prediction)
62
 * @method void expect($prediction)
63
 * @method void amGoingTo($argumentation)
64
 * @method void am($role)
65
 * @method void lookForwardTo($achieveValue)
66
 * @method void comment($description)
67
 * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = null)
68
 *
69
 * @SuppressWarnings(\PyzTest\Glue\Checkout\PHPMD)
70
 */
71
class CheckoutApiTester extends ApiEndToEndTester
72
{
73
    use _generated\CheckoutApiTesterActions;
74
75
    /**
76
     * @var string
77
     */
78
    protected const REQUEST_PARAM_PAYMENT_METHOD_NAME_INVOICE = 'Invoice';
79
80
    /**
81
     * @var string
82
     */
83
    protected const REQUEST_PARAM_PAYMENT_PROVIDER_NAME_DUMMY_PAYMENT = 'DummyMarketplacePayment';
84
85
    /**
86
     * @var string
87
     */
88
    protected const QUOTE_ITEM_OVERRIDE_DATA_PRODUCT = 'product';
89
90
    /**
91
     * @var string
92
     */
93
    protected const QUOTE_ITEM_OVERRIDE_DATA_SHIPMENT = 'shipment';
94
95
    /**
96
     * @var string
97
     */
98
    protected const QUOTE_ITEM_OVERRIDE_DATA_QUANTITY = 'quantity';
99
100
    /**
101
     * @var int
102
     */
103
    protected const DEFAULT_QUOTE_ITEM_QUANTITY = 10;
104
105
    /**
106
     * @return void
107
     */
108
    public function assertCheckoutResponseResourceHasCorrectData(): void
109
    {
110
        $this->amSure('The returned resource id should be null')
111
            ->whenI()
112
            ->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

112
            ->/** @scrutinizer ignore-call */ seeSingleResourceIdEqualTo('');
Loading history...
113
114
        $attributes = $this->getDataFromResponseByJsonPath('$.data.attributes');
115
116
        $this->assertNotEmpty(
117
            $attributes[RestCheckoutResponseTransfer::ORDER_REFERENCE],
118
            'The returned resource attributes order reference should not be empty',
119
        );
120
        $this->assertArrayHasKey(
121
            RestCheckoutResponseTransfer::IS_EXTERNAL_REDIRECT,
122
            $attributes,
123
            'The returned resource attributes should have an external redirect key',
124
        );
125
        $this->assertArrayHasKey(
126
            RestCheckoutResponseTransfer::REDIRECT_URL,
127
            $attributes,
128
            'The returned resource attributes should have a redirect URL key',
129
        );
130
    }
131
132
    /**
133
     * @return void
134
     */
135
    public function assertCheckoutDataResponseResourceHasCorrectData(): void
136
    {
137
        $this->amSure('The returned resource id should be null')
138
            ->whenI()
139
            ->seeSingleResourceIdEqualTo('');
140
141
        $attributes = $this->getDataFromResponseByJsonPath('$.data.attributes');
142
143
        $this->assertEmpty(
144
            $attributes[RestCheckoutDataTransfer::ADDRESSES],
145
            'The returned resource attributes addresses should be an empty array',
146
        );
147
    }
148
149
    /**
150
     * @param int $price
151
     *
152
     * @return void
153
     */
154
    public function assertShipmentExpensesHaveCorrectPrice(int $price): void
155
    {
156
        $this->amSure('The returned resource should have included orders resource')
157
            ->whenI()
158
            ->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

158
            ->/** @scrutinizer ignore-call */ seeIncludesContainResourceOfType(OrdersRestApiConfig::RESOURCE_ORDERS);
Loading history...
159
160
        $ordersAttributes = $this->getDataFromResponseByJsonPath(
161
            sprintf('$.included[?(@.type == %1$s)].attributes', json_encode(OrdersRestApiConfig::RESOURCE_ORDERS)),
162
        );
163
164
        $this->assertNotNull($ordersAttributes);
165
        $this->assertCount(1, $ordersAttributes);
166
        $restOrdersDetailsAttributesTransfer = (new RestOrderDetailsAttributesTransfer())->fromArray($ordersAttributes[0], true);
167
        $this->assertCount(1, $restOrdersDetailsAttributesTransfer->getExpenses());
168
169
        /** @var \Generated\Shared\Transfer\RestOrderExpensesAttributesTransfer $restOrderExpensesAttributesTransfer */
170
        $restOrderExpensesAttributesTransfer = $restOrdersDetailsAttributesTransfer->getExpenses()->getIterator()->current();
171
        $this->assertSame(ShipmentConfig::SHIPMENT_EXPENSE_TYPE, $restOrderExpensesAttributesTransfer->getType());
172
        $this->assertSame($price, $restOrderExpensesAttributesTransfer->getSumPrice());
173
    }
174
175
    /**
176
     * @param array<string> $includes
177
     *
178
     * @return string
179
     */
180
    public function buildCheckoutUrl(array $includes = []): string
181
    {
182
        return $this->formatFullUrl(
183
            '{resourceCheckout}' . $this->formatQueryInclude($includes),
184
            [
185
                'resourceCheckout' => CheckoutRestApiConfig::RESOURCE_CHECKOUT,
186
            ],
187
        );
188
    }
189
190
    /**
191
     * @param array<string> $includes
192
     *
193
     * @return string
194
     */
195
    public function buildCheckoutDataUrl(array $includes = []): string
196
    {
197
        return $this->formatFullUrl(
198
            '{resourceCheckoutData}' . $this->formatQueryInclude($includes),
199
            [
200
                'resourceCheckoutData' => CheckoutRestApiConfig::RESOURCE_CHECKOUT_DATA,
201
            ],
202
        );
203
    }
204
205
    /**
206
     * @return \Spryker\Zed\Store\Business\StoreFacadeInterface
207
     */
208
    public function getStoreFacade(): StoreFacadeInterface
209
    {
210
        return $this->getLocator()
211
            ->store()
212
            ->facade();
213
    }
214
215
    /**
216
     * @return \Spryker\Zed\Customer\Business\CustomerFacadeInterface
217
     */
218
    public function getCustomerFacade(): CustomerFacadeInterface
219
    {
220
        return $this->getLocator()
221
            ->customer()
222
            ->facade();
223
    }
224
225
    /**
226
     * @return \Spryker\Zed\Cart\Business\CartFacadeInterface
227
     */
228
    public function getCartFacade(): CartFacadeInterface
229
    {
230
        return $this->getLocator()->cart()->facade();
231
    }
232
233
    /**
234
     * @param \Generated\Shared\Transfer\AddressTransfer $addressTransfer
235
     *
236
     * @return array
237
     */
238
    public function getAddressRequestPayload(AddressTransfer $addressTransfer): array
239
    {
240
        return [
241
            RestAddressTransfer::SALUTATION => $addressTransfer->getSalutation(),
242
            RestAddressTransfer::FIRST_NAME => $addressTransfer->getFirstName(),
243
            RestAddressTransfer::LAST_NAME => $addressTransfer->getLastName(),
244
            RestAddressTransfer::ADDRESS1 => $addressTransfer->getAddress1(),
245
            RestAddressTransfer::ADDRESS2 => $addressTransfer->getAddress2(),
246
            RestAddressTransfer::ADDRESS3 => $addressTransfer->getAddress3(),
247
            RestAddressTransfer::ZIP_CODE => $addressTransfer->getZipCode(),
248
            RestAddressTransfer::CITY => $addressTransfer->getCity(),
249
            RestAddressTransfer::ISO2_CODE => $addressTransfer->getIso2Code(),
250
            RestAddressTransfer::PHONE => $addressTransfer->getPhone(),
251
            RestCustomerTransfer::EMAIL => $addressTransfer->getEmail(),
252
            RestAddressTransfer::IS_DEFAULT_BILLING => $addressTransfer->getIsDefaultBilling(),
253
            RestAddressTransfer::IS_DEFAULT_SHIPPING => $addressTransfer->getIsDefaultShipping(),
254
        ];
255
    }
256
257
    /**
258
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
259
     *
260
     * @return array
261
     */
262
    public function getCustomerRequestPayload(CustomerTransfer $customerTransfer): array
263
    {
264
        return [
265
            RestCustomerTransfer::SALUTATION => $customerTransfer->getSalutation(),
266
            RestCustomerTransfer::FIRST_NAME => $customerTransfer->getFirstName(),
267
            RestCustomerTransfer::LAST_NAME => $customerTransfer->getLastName(),
268
            RestCustomerTransfer::EMAIL => $customerTransfer->getEmail(),
269
        ];
270
    }
271
272
    /**
273
     * @param string $paymentMethodName
274
     * @param string $paymentProviderName
275
     *
276
     * @return array
277
     */
278
    public function getPaymentRequestPayload(
279
        string $paymentMethodName = self::REQUEST_PARAM_PAYMENT_METHOD_NAME_INVOICE,
280
        string $paymentProviderName = self::REQUEST_PARAM_PAYMENT_PROVIDER_NAME_DUMMY_PAYMENT,
281
    ): array {
282
        return [
283
            [
284
                RestPaymentTransfer::PAYMENT_METHOD_NAME => $paymentMethodName,
285
                RestPaymentTransfer::PAYMENT_PROVIDER_NAME => $paymentProviderName,
286
            ],
287
        ];
288
    }
289
290
    /**
291
     * @param int $idShipmentMethod
292
     *
293
     * @return array
294
     */
295
    public function getShipmentRequestPayload(int $idShipmentMethod): array
296
    {
297
        return [
298
            RestShipmentTransfer::ID_SHIPMENT_METHOD => $idShipmentMethod,
299
        ];
300
    }
301
302
    /**
303
     * @param \Generated\Shared\Transfer\ItemTransfer $itemTransfer
304
     * @param \Generated\Shared\Transfer\AddressTransfer|null $addressTransfer
305
     *
306
     * @return array<string, mixed>
307
     */
308
    public function getSplitShipmentRequestPayload(ItemTransfer $itemTransfer, ?AddressTransfer $addressTransfer = null): array
309
    {
310
        $shippingAddressPayload = $addressTransfer
311
            ? [RestAddressTransfer::ID => $addressTransfer->getUuidOrFail()]
312
            : $this->getAddressRequestPayload($itemTransfer->getShipmentOrFail()->getShippingAddressOrFail());
313
314
        return [
315
            RestShipmentsTransfer::ID_SHIPMENT_METHOD => $itemTransfer->getShipmentOrFail()->getMethodOrFail()->getIdShipmentMethodOrFail(),
316
            RestShipmentsTransfer::ITEMS => [$itemTransfer->getGroupKeyOrFail()],
317
            RestShipmentsTransfer::SHIPPING_ADDRESS => $shippingAddressPayload,
318
            RestShipmentsTransfer::REQUESTED_DELIVERY_DATE => (new DateTime('tomorrow'))->format('Y-m-d'),
319
        ];
320
    }
321
322
    /**
323
     * @param \Generated\Shared\Transfer\ProductConcreteTransfer $productConcreteTransfer
324
     * @param \Generated\Shared\Transfer\ShipmentMethodTransfer $shipmentMethodTransfer
325
     * @param int $quantity
326
     *
327
     * @return array
328
     */
329
    public function getQuoteItemOverrideData(
330
        ProductConcreteTransfer $productConcreteTransfer,
331
        ShipmentMethodTransfer $shipmentMethodTransfer,
332
        int $quantity = self::DEFAULT_QUOTE_ITEM_QUANTITY,
333
    ): array {
334
        return [
335
            static::QUOTE_ITEM_OVERRIDE_DATA_PRODUCT => $productConcreteTransfer,
336
            static::QUOTE_ITEM_OVERRIDE_DATA_SHIPMENT => [
337
                ShipmentTransfer::METHOD => $shipmentMethodTransfer,
338
            ],
339
            static::QUOTE_ITEM_OVERRIDE_DATA_QUANTITY => $quantity,
340
        ];
341
    }
342
343
    /**
344
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
345
     *
346
     * @return void
347
     */
348
    public function authorizeCustomerToGlue(CustomerTransfer $customerTransfer): void
349
    {
350
        $oauthResponseTransfer = $this->haveAuthorizationToGlue($customerTransfer);
351
        $this->amBearerAuthenticated($oauthResponseTransfer->getAccessToken());
352
    }
353
354
    /**
355
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
356
     * @param array $overrideItems
357
     * @param string $priceMode
358
     *
359
     * @return \Generated\Shared\Transfer\QuoteTransfer
360
     */
361
    public function havePersistentQuoteWithItemsAndItemLevelShipment(
362
        CustomerTransfer $customerTransfer,
363
        array $overrideItems = [],
364
        string $priceMode = PriceConfig::PRICE_MODE_GROSS,
365
    ): QuoteTransfer {
366
        return $this->havePersistentQuote([
367
            QuoteTransfer::CUSTOMER => $customerTransfer,
368
            QuoteTransfer::TOTALS => (new TotalsTransfer())
369
                ->setSubtotal(random_int(1000, 10000))
370
                ->setPriceToPay(random_int(1000, 10000)),
371
            QuoteTransfer::ITEMS => $this->mapProductConcreteTransfersToQuoteTransferItemsWithItemLevelShipment($overrideItems),
372
            QuoteTransfer::STORE => [StoreTransfer::NAME => 'DE'],
373
            QuoteTransfer::PRICE_MODE => $priceMode,
374
            QuoteTransfer::BILLING_ADDRESS => (new AddressBuilder())->build(),
375
        ]);
376
    }
377
378
    /**
379
     * @param array $overrideCustomer
380
     *
381
     * @return \Generated\Shared\Transfer\QuoteTransfer
382
     */
383
    public function haveEmptyPersistentQuote(array $overrideCustomer = []): QuoteTransfer
384
    {
385
        return $this->havePersistentQuote([
386
            QuoteTransfer::CUSTOMER => (new CustomerBuilder($overrideCustomer))->build(),
387
            QuoteTransfer::BILLING_ADDRESS => (new AddressBuilder())->build(),
388
        ]);
389
    }
390
391
    /**
392
     * @return \Generated\Shared\Transfer\ProductConcreteTransfer
393
     */
394
    public function haveProductWithStock(): ProductConcreteTransfer
395
    {
396
        $productConcreteTransfer = $this->haveFullProduct();
397
398
        $this->haveProductInStockForStore($this->getStoreFacade()->getCurrentStore(), [
399
            StockProductTransfer::SKU => $productConcreteTransfer->getSku(),
400
            StockProductTransfer::IS_NEVER_OUT_OF_STOCK => 1,
401
        ]);
402
403
        $priceProductOverride = [
404
            PriceProductTransfer::SKU_PRODUCT_ABSTRACT => $productConcreteTransfer->getAbstractSku(),
405
            PriceProductTransfer::SKU_PRODUCT => $productConcreteTransfer->getSku(),
406
            PriceProductTransfer::ID_PRODUCT => $productConcreteTransfer->getIdProductConcrete(),
407
            PriceProductTransfer::PRICE_TYPE_NAME => 'DEFAULT',
408
            PriceProductTransfer::MONEY_VALUE => [
409
                MoneyValueTransfer::NET_AMOUNT => 770,
410
                MoneyValueTransfer::GROSS_AMOUNT => 880,
411
            ],
412
        ];
413
        $this->havePriceProduct($priceProductOverride);
414
415
        return $productConcreteTransfer;
416
    }
417
418
    /**
419
     * @param array $override
420
     *
421
     * @return \Generated\Shared\Transfer\CustomerTransfer
422
     */
423
    public function createCustomerTransfer(array $override = []): CustomerTransfer
424
    {
425
        return (new CustomerBuilder($override))->build();
426
    }
427
428
    /**
429
     * @param array $override
430
     *
431
     * @return \Generated\Shared\Transfer\CustomerTransfer
432
     */
433
    public function haveCustomerWithPersistentAddress(array $override = []): CustomerTransfer
434
    {
435
        $customerTransfer = $this->haveCustomer($override);
436
437
        return $this->haveAddressForCustomer($customerTransfer);
438
    }
439
440
    /**
441
     * @param array $paymentMethodOverrideData
442
     * @param array $storeOverrideData
443
     *
444
     * @return \Generated\Shared\Transfer\PaymentMethodTransfer
445
     */
446
    public function havePaymentMethodWithStore(
447
        array $paymentMethodOverrideData = [],
448
        array $storeOverrideData = [
449
            StoreTransfer::NAME => 'DE',
450
            StoreTransfer::DEFAULT_CURRENCY_ISO_CODE => 'EUR',
451
            StoreTransfer::AVAILABLE_CURRENCY_ISO_CODES => ['EUR'],
452
        ],
453
    ): PaymentMethodTransfer {
454
        $storeTransfer = $this->haveStore($storeOverrideData);
455
        $storeRelationTransfer = (new StoreRelationBuilder())->seed([
456
            StoreRelationTransfer::ID_STORES => [
457
                $storeTransfer->getIdStore(),
458
            ],
459
            StoreRelationTransfer::STORES => [
460
                $storeTransfer,
461
            ],
462
        ])->build();
463
464
        $paymentMethodOverrideData = array_merge($paymentMethodOverrideData, [PaymentMethodTransfer::STORE_RELATION => $storeRelationTransfer]);
465
466
        return $this->havePaymentMethod($paymentMethodOverrideData);
467
    }
468
469
    /**
470
     * @param \Generated\Shared\Transfer\MerchantTransfer $merchantTransfer
471
     * @param \Generated\Shared\Transfer\ProductConcreteTransfer $productConcreteTransfer
472
     *
473
     * @return \Generated\Shared\Transfer\ProductOfferTransfer
474
     */
475
    public function createProductOfferWithStock(
476
        MerchantTransfer $merchantTransfer,
477
        ProductConcreteTransfer $productConcreteTransfer,
478
    ): ProductOfferTransfer {
479
        $storeTransfer = $this->getStoreFacade()->getCurrentStore();
480
481
        $productOfferTransfer = $this->haveProductOffer([
482
            ProductOfferTransfer::CONCRETE_SKU => $productConcreteTransfer->getSkuOrFail(),
483
            ProductOfferTransfer::ID_PRODUCT_CONCRETE => $productConcreteTransfer->getIdProductConcreteOrFail(),
484
            ProductOfferTransfer::STORES => new ArrayObject([$storeTransfer]),
485
            ProductOfferTransfer::MERCHANT_REFERENCE => $merchantTransfer->getMerchantReferenceOrFail(),
486
        ]);
487
488
        $productOfferStockTransfer = $this->haveProductOfferStock([
489
            ProductOfferStockTransfer::ID_PRODUCT_OFFER => $productOfferTransfer->getIdProductOfferOrFail(),
490
            ProductOfferStockTransfer::QUANTITY => 1,
491
            ProductOfferStockTransfer::IS_NEVER_OUT_OF_STOCK => 1,
492
            ProductOfferStockTransfer::STOCK => [
493
                StockTransfer::STORE_RELATION => [
494
                    StoreRelationTransfer::ID_STORES => [$storeTransfer->getIdStore()],
495
                ],
496
            ],
497
        ]);
498
499
        $this->updateStock($productOfferStockTransfer->getStock()->setIsActive(true));
500
501
        $this->havePriceProductOffer([
502
            PriceProductOfferTransfer::FK_PRODUCT_OFFER => $productOfferTransfer->getIdProductOfferOrFail(),
503
            PriceProductTransfer::SKU_PRODUCT => $productConcreteTransfer->getSkuOrFail(),
504
            PriceProductTransfer::SKU_PRODUCT_ABSTRACT => $productConcreteTransfer->getAbstractSkuOrFail(),
505
            PriceProductTransfer::PRICE_TYPE_NAME => 'DEFAULT',
506
            PriceProductTransfer::MONEY_VALUE => [
507
                MoneyValueTransfer::NET_AMOUNT => 770,
508
                MoneyValueTransfer::GROSS_AMOUNT => 880,
509
            ],
510
        ]);
511
512
        return $productOfferTransfer;
513
    }
514
515
    /**
516
     * @param \Generated\Shared\Transfer\ItemTransfer $itemTransfer
517
     * @param \Generated\Shared\Transfer\CompanyUnitAddressTransfer $companyUnitAddressTransfer
518
     *
519
     * @return array<string, mixed>
520
     */
521
    public function getSplitShipmentRequestPayloadWithCompanyBusinessUnitAddress(
522
        ItemTransfer $itemTransfer,
523
        CompanyUnitAddressTransfer $companyUnitAddressTransfer,
524
    ): array {
525
        return [
526
            RestShipmentsTransfer::ID_SHIPMENT_METHOD => $itemTransfer->getShipmentOrFail()->getMethodOrFail()->getIdShipmentMethodOrFail(),
527
            RestShipmentsTransfer::ITEMS => [$itemTransfer->getGroupKeyOrFail()],
528
            RestShipmentsTransfer::SHIPPING_ADDRESS => [
529
                RestAddressTransfer::ID_COMPANY_BUSINESS_UNIT_ADDRESS => $companyUnitAddressTransfer->getUuidOrFail(),
530
            ],
531
            RestShipmentsTransfer::REQUESTED_DELIVERY_DATE => (new DateTime('tomorrow'))->format('Y-m-d'),
532
        ];
533
    }
534
535
    /**
536
     * @param \Generated\Shared\Transfer\AddressTransfer $addressTransfer
537
     *
538
     * @return void
539
     */
540
    public function assertCustomerBillingAddressInOrders(AddressTransfer $addressTransfer): void
541
    {
542
        $jsonPath = sprintf('$..included[?(@.type == \'%s\')]', 'orders');
543
        $billingAddress = $this->getDataFromResponseByJsonPath($jsonPath)[0]['attributes']['billingAddress'];
544
545
        $this->assertSame($addressTransfer->getAddress1(), $billingAddress['address1']);
546
        $this->assertSame($addressTransfer->getAddress2(), $billingAddress['address2']);
547
        $this->assertSame($addressTransfer->getAddress3(), $billingAddress['address3']);
548
        $this->assertSame($addressTransfer->getCompany(), $billingAddress['company']);
549
        $this->assertSame($addressTransfer->getCity(), $billingAddress['city']);
550
        $this->assertSame($addressTransfer->getZipCode(), $billingAddress['zipCode']);
551
        $this->assertSame($addressTransfer->getIso2Code(), $billingAddress['iso2Code']);
552
    }
553
554
    /**
555
     * @param \Generated\Shared\Transfer\AddressTransfer $addressTransfer
556
     *
557
     * @return void
558
     */
559
    public function assertCustomerShippingAddressInOrderShipments(
560
        AddressTransfer $addressTransfer,
561
    ): void {
562
        $jsonPath = sprintf('$..included[?(@.type == \'%s\')]', 'order-shipments');
563
        $shippingAddress = $this->getDataFromResponseByJsonPath($jsonPath)[0]['attributes']['shippingAddress'];
564
565
        $this->assertSame($addressTransfer->getAddress1(), $shippingAddress['address1']);
566
        $this->assertSame($addressTransfer->getAddress2(), $shippingAddress['address2']);
567
        $this->assertSame($addressTransfer->getAddress3(), $shippingAddress['address3']);
568
        $this->assertSame($addressTransfer->getCompany(), $shippingAddress['company']);
569
        $this->assertSame($addressTransfer->getCity(), $shippingAddress['city']);
570
        $this->assertSame($addressTransfer->getZipCode(), $shippingAddress['zipCode']);
571
        $this->assertSame($addressTransfer->getIso2Code(), $shippingAddress['iso2Code']);
572
    }
573
574
    /**
575
     * @param \Generated\Shared\Transfer\CompanyUnitAddressTransfer $companyUnitAddressTransfer
576
     *
577
     * @return void
578
     */
579
    public function assertCompanyBusinessUnitBillingAddressInOrders(
580
        CompanyUnitAddressTransfer $companyUnitAddressTransfer,
581
    ): void {
582
        $jsonPath = sprintf('$..included[?(@.type == \'%s\')]', 'orders');
583
        $billingAddress = $this->getDataFromResponseByJsonPath($jsonPath)[0]['attributes']['billingAddress'];
584
585
        $this->assertSame($companyUnitAddressTransfer->getAddress1(), $billingAddress['address1']);
586
        $this->assertSame($companyUnitAddressTransfer->getAddress2(), $billingAddress['address2']);
587
        $this->assertSame($companyUnitAddressTransfer->getAddress3(), $billingAddress['address3']);
588
        $this->assertSame($companyUnitAddressTransfer->getCompany()->getName(), $billingAddress['company']);
589
        $this->assertSame($companyUnitAddressTransfer->getCity(), $billingAddress['city']);
590
        $this->assertSame($companyUnitAddressTransfer->getZipCode(), $billingAddress['zipCode']);
591
        $this->assertSame($companyUnitAddressTransfer->getIso2Code(), $billingAddress['iso2Code']);
592
    }
593
594
    /**
595
     * @param \Generated\Shared\Transfer\CompanyUnitAddressTransfer $companyUnitAddressTransfer
596
     *
597
     * @return void
598
     */
599
    public function assertCompanyBusinessUnitShippingAddressInOrderShipments(
600
        CompanyUnitAddressTransfer $companyUnitAddressTransfer,
601
    ): void {
602
        $jsonPath = sprintf('$..included[?(@.type == \'%s\')]', 'order-shipments');
603
        $shippingAddress = $this->getDataFromResponseByJsonPath($jsonPath)[0]['attributes']['shippingAddress'];
604
605
        $this->assertSame($companyUnitAddressTransfer->getAddress1(), $shippingAddress['address1']);
606
        $this->assertSame($companyUnitAddressTransfer->getAddress2(), $shippingAddress['address2']);
607
        $this->assertSame($companyUnitAddressTransfer->getAddress3(), $shippingAddress['address3']);
608
        $this->assertSame($companyUnitAddressTransfer->getCompany()->getName(), $shippingAddress['company']);
609
        $this->assertSame($companyUnitAddressTransfer->getCity(), $shippingAddress['city']);
610
        $this->assertSame($companyUnitAddressTransfer->getZipCode(), $shippingAddress['zipCode']);
611
        $this->assertSame($companyUnitAddressTransfer->getIso2Code(), $shippingAddress['iso2Code']);
612
    }
613
614
    /**
615
     * @param \Generated\Shared\Transfer\CustomerTransfer $customerTransfer
616
     *
617
     * @return \Generated\Shared\Transfer\CustomerTransfer
618
     */
619
    protected function haveAddressForCustomer(CustomerTransfer $customerTransfer): CustomerTransfer
620
    {
621
        $addressTransfer = (new AddressBuilder([
622
            AddressTransfer::EMAIL => $customerTransfer->getEmail(),
623
            AddressTransfer::FK_CUSTOMER => $customerTransfer->getIdCustomer(),
624
            AddressTransfer::FIRST_NAME => $customerTransfer->getFirstName(),
625
            AddressTransfer::LAST_NAME => $customerTransfer->getLastName(),
626
        ]))->build();
627
        $customerFacade = $this->getCustomerFacade();
628
        $customerFacade->createAddress($addressTransfer);
629
630
        return $customerFacade->getCustomer($customerTransfer);
631
    }
632
633
    /**
634
     * @param array $overrideItems
635
     *
636
     * @return array
637
     */
638
    protected function mapProductConcreteTransfersToQuoteTransferItemsWithItemLevelShipment(array $overrideItems = []): array
639
    {
640
        $quoteTransferItems = [];
641
642
        foreach ($overrideItems as $overrideItem) {
643
            $productConcreteTransfer = $this->getProductConcreteTransferFromOverrideItemData($overrideItem);
644
            $overrideShipment = $this->getOverrideShipmentDataFromOverrideItemData($overrideItem);
645
            /** @var \Generated\Shared\Transfer\ProductOfferTransfer|null $productOfferTransfer */
646
            $productOfferTransfer = $productConcreteTransfer->getOffers()->getIterator()->current();
647
648
            $quoteTransferItems[] = (new ItemBuilder([
649
                ItemTransfer::SKU => $productConcreteTransfer->getSku(),
650
                ItemTransfer::GROUP_KEY => $productConcreteTransfer->getSku(),
651
                ItemTransfer::ABSTRACT_SKU => $productConcreteTransfer->getAbstractSku(),
652
                ItemTransfer::ID_PRODUCT_ABSTRACT => $productConcreteTransfer->getFkProductAbstract(),
653
                ItemTransfer::QUANTITY => $this->getQuoteItemQuantityFromOverrideItemData($overrideItem),
654
                ItemTransfer::PRODUCT_OFFER_REFERENCE => $productOfferTransfer?->getProductOfferReference(),
655
                ItemTransfer::MERCHANT_REFERENCE => $productOfferTransfer?->getMerchantReference(),
656
            ]))->withShipment((new ShipmentBuilder($overrideShipment))
657
                ->withMethod()
658
                ->withShippingAddress())
659
                ->build()
660
                ->modifiedToArray();
661
        }
662
663
        return $quoteTransferItems;
664
    }
665
666
    /**
667
     * @param array $overrideItem
668
     *
669
     * @return \Generated\Shared\Transfer\ProductConcreteTransfer
670
     */
671
    protected function getProductConcreteTransferFromOverrideItemData(array $overrideItem): ProductConcreteTransfer
672
    {
673
        return $overrideItem[static::QUOTE_ITEM_OVERRIDE_DATA_PRODUCT];
674
    }
675
676
    /**
677
     * @param array $overrideItem
678
     *
679
     * @return array
680
     */
681
    protected function getOverrideShipmentDataFromOverrideItemData(array $overrideItem): array
682
    {
683
        return $overrideItem[static::QUOTE_ITEM_OVERRIDE_DATA_SHIPMENT];
684
    }
685
686
    /**
687
     * @param array $overrideItem
688
     *
689
     * @return int
690
     */
691
    protected function getQuoteItemQuantityFromOverrideItemData(array $overrideItem): int
692
    {
693
        return $overrideItem[static::QUOTE_ITEM_OVERRIDE_DATA_QUANTITY] ?? static::DEFAULT_QUOTE_ITEM_QUANTITY;
694
    }
695
696
    /**
697
     * @param array<string> $includes
698
     *
699
     * @return string
700
     */
701
    protected function formatQueryInclude(array $includes = []): string
702
    {
703
        if (!$includes) {
704
            return '';
705
        }
706
707
        return sprintf('?%s=%s', RequestConstantsInterface::QUERY_INCLUDE, implode(',', $includes));
708
    }
709
}
710