CalculationBusinessTester   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 305
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 32
eloc 157
dl 0
loc 305
rs 9.84
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A createAbstractProduct() 0 9 1
A createProductOptionTransfer() 0 18 3
A createAbstractProductWithTaxExemption() 0 12 1
A recalculateCanceledAmount() 0 20 3
A createCurrencyTransfer() 0 4 1
A getCurrentStoreTransfer() 0 5 1
A getCurrentShippingAddress() 0 3 1
A createExpenseTransfer() 0 15 3
A isCanceledAmount() 0 9 3
A resetCurrentDiscounts() 0 8 2
A createItemTransfer() 0 20 3
A getCurrency() 0 3 1
A createCalculationFacade() 0 22 2
A createTaxSetTax() 0 7 1
A getIncrementNumber() 0 3 1
A createTaxSet() 0 7 1
A createDiscountTransfer() 0 6 1
A createProductOptionValue() 0 25 1
A createDiscounts() 0 43 1
A createAbstractProductWithTaxSet() 0 15 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
declare(strict_types = 1);
9
10
namespace PyzTest\Zed\Calculation;
11
12
use Codeception\Actor;
13
use DateTime;
14
use Generated\Shared\Transfer\AddressTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\AddressTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Generated\Shared\Transfer\CurrencyTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\CurrencyTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Generated\Shared\Transfer\DiscountTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\DiscountTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Generated\Shared\Transfer\ExpenseTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\ExpenseTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use Generated\Shared\Transfer\ItemTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\ItemTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use Generated\Shared\Transfer\ProductOptionTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\ProductOptionTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
use Generated\Shared\Transfer\QuoteTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\QuoteTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use Generated\Shared\Transfer\StoreTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\StoreTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use Orm\Zed\Country\Persistence\SpyCountryQuery;
23
use Orm\Zed\Currency\Persistence\SpyCurrency;
24
use Orm\Zed\Currency\Persistence\SpyCurrencyQuery;
25
use Orm\Zed\Discount\Persistence\SpyDiscount;
26
use Orm\Zed\Discount\Persistence\SpyDiscountAmount;
27
use Orm\Zed\Discount\Persistence\SpyDiscountQuery;
28
use Orm\Zed\Discount\Persistence\SpyDiscountStore;
29
use Orm\Zed\Discount\Persistence\SpyDiscountVoucher;
30
use Orm\Zed\Discount\Persistence\SpyDiscountVoucherPool;
31
use Orm\Zed\Product\Persistence\SpyProductAbstract;
32
use Orm\Zed\ProductOption\Persistence\SpyProductOptionGroup;
33
use Orm\Zed\ProductOption\Persistence\SpyProductOptionValue;
34
use Orm\Zed\Tax\Persistence\SpyTaxRate;
35
use Orm\Zed\Tax\Persistence\SpyTaxSet;
36
use Orm\Zed\Tax\Persistence\SpyTaxSetTax;
37
use Pyz\Zed\Calculation\CalculationDependencyProvider;
38
use Pyz\Zed\Discount\DiscountDependencyProvider;
39
use Spryker\Shared\Calculation\CalculationPriceMode;
40
use Spryker\Shared\Tax\TaxConstants;
41
use Spryker\Zed\Calculation\Business\CalculationBusinessFactory;
42
use Spryker\Zed\Calculation\Business\CalculationFacade;
43
use Spryker\Zed\Calculation\Communication\Plugin\Calculator\GrandTotalCalculatorPlugin;
44
use Spryker\Zed\Calculation\Communication\Plugin\Calculator\RefundableAmountCalculatorPlugin;
45
use Spryker\Zed\Calculation\Communication\Plugin\Calculator\RefundTotalCalculatorPlugin;
46
use Spryker\Zed\Calculation\Dependency\Service\CalculationToUtilTextBridge;
47
use Spryker\Zed\Kernel\Container;
48
49
/**
50
 * Inherited Methods
51
 *
52
 * @method void wantToTest($text)
53
 * @method void wantTo($text)
54
 * @method void execute($callable)
55
 * @method void expectTo($prediction)
56
 * @method void expect($prediction)
57
 * @method void amGoingTo($argumentation)
58
 * @method void am($role)
59
 * @method void lookForwardTo($achieveValue)
60
 * @method void comment($description)
61
 * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
62
 *
63
 * @SuppressWarnings(\PyzTest\Zed\Calculation\PHPMD)
64
 */
65
class CalculationBusinessTester extends Actor
66
{
67
    use _generated\CalculationBusinessTesterActions;
0 ignored issues
show
Bug introduced by
The type PyzTest\Zed\Calculation\...onBusinessTesterActions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
68
69
    protected int $incrementNumber = 0;
70
71
    protected const COUNTRY_DE = 'DE';
72
73
    public function createDiscounts(int $discountAmount, string $calculatorType, string $sku = '*'): SpyDiscountVoucher
74
    {
75
        $discountVoucherPoolEntity = new SpyDiscountVoucherPool();
76
        $discountVoucherPoolEntity->setName('test-pool' . $this->getIncrementNumber());
77
        $discountVoucherPoolEntity->setIsActive(true);
78
        $discountVoucherPoolEntity->save();
79
80
        $discountVoucherEntity = new SpyDiscountVoucher();
81
        $discountVoucherEntity->setCode('spryker-test' . $this->getIncrementNumber());
82
        $discountVoucherEntity->setIsActive(true);
83
        $discountVoucherEntity->setFkDiscountVoucherPool($discountVoucherPoolEntity->getIdDiscountVoucherPool());
84
        $discountVoucherEntity->save();
85
86
        $discountEntity = new SpyDiscount();
87
        $discountEntity->setAmount($discountAmount);
88
        $discountEntity->setDisplayName('test1' . $this->getIncrementNumber());
89
        $discountEntity->setIsActive(1);
90
        $discountEntity->setValidFrom(new DateTime('1985-07-01'));
91
        $discountEntity->setValidTo(new DateTime('2030-07-01'));
92
        $discountEntity->setCalculatorPlugin($calculatorType);
93
        $discountEntity->setCollectorQueryString('sku = "' . $sku . '"');
94
95
        $discountEntity->setFkDiscountVoucherPool($discountVoucherPoolEntity->getIdDiscountVoucherPool());
96
        $discountEntity->save();
97
98
        (new SpyDiscountStore())
99
            ->setFkDiscount($discountEntity->getIdDiscount())
100
            ->setFkStore($this->getCurrentStoreTransfer()->getIdStore())
101
            ->save();
102
103
        $discountAmountEntity = new SpyDiscountAmount();
104
        $currencyEntity = $this->getCurrency();
105
        $discountAmountEntity->setFkCurrency($currencyEntity->getIdCurrency());
106
        $discountAmountEntity->setNetAmount($discountAmount);
107
        $discountAmountEntity->setGrossAmount($discountAmount);
108
        $discountAmountEntity->setFkDiscount($discountEntity->getIdDiscount());
109
        $discountAmountEntity->save();
110
111
        $discountEntity->reload(true);
112
        $pool = $discountEntity->getVoucherPool();
113
        $pool->getDiscountVouchers();
114
115
        return $discountVoucherEntity;
116
    }
117
118
    public function createExpenseTransfer(int $price, string $priceMode, float $taxRate, int $quantity): ExpenseTransfer
119
    {
120
        $expenseTransfer = new ExpenseTransfer();
121
        $expenseTransfer->setTaxRate($taxRate);
122
        $expenseTransfer->setQuantity($quantity);
123
124
        if ($priceMode === CalculationPriceMode::PRICE_MODE_GROSS) {
125
            $expenseTransfer->setUnitGrossPrice($price);
126
        }
127
128
        if ($priceMode === CalculationPriceMode::PRICE_MODE_NET) {
129
            $expenseTransfer->setUnitNetPrice($price);
130
        }
131
132
        return $expenseTransfer;
133
    }
134
135
    public function createCalculationFacade(array $calculatorPlugins = []): CalculationFacade
136
    {
137
        if (!$calculatorPlugins) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $calculatorPlugins of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
138
            return new CalculationFacade();
139
        }
140
141
        $calculationFacade = new CalculationFacade();
142
143
        $calculationBusinessFactory = new CalculationBusinessFactory();
144
145
        $container = new Container();
146
        $container[CalculationDependencyProvider::QUOTE_CALCULATOR_PLUGIN_STACK] = $calculatorPlugins;
147
        $container[CalculationDependencyProvider::PLUGINS_QUOTE_POST_RECALCULATE] = [];
148
149
        $container->set(CalculationDependencyProvider::SERVICE_UTIL_TEXT, function (Container $container) {
150
            return new CalculationToUtilTextBridge($container->getLocator()->utilText()->service());
151
        });
152
153
        $calculationBusinessFactory->setContainer($container);
154
        $calculationFacade->setFactory($calculationBusinessFactory);
155
156
        return $calculationFacade;
157
    }
158
159
    public function resetCurrentDiscounts(): void
160
    {
161
        $discounts = SpyDiscountQuery::create()->find();
162
163
        foreach ($discounts as $discountEntity) {
164
            $discountEntity->setIsActive(false);
165
166
            $discountEntity->save();
167
        }
168
    }
169
170
    /**
171
     * @param array<\Generated\Shared\Transfer\ItemTransfer> $items
172
     * @param \Generated\Shared\Transfer\QuoteTransfer $quoteTransfer
173
     */
174
    public function recalculateCanceledAmount(array $items, QuoteTransfer $quoteTransfer): QuoteTransfer
175
    {
176
        if (!$this->isCanceledAmount($items)) {
177
            return $quoteTransfer;
178
        }
179
180
        foreach ($quoteTransfer->getItems() as $itemTransferIndex => $itemTransfer) {
181
            $itemTransfer->setCanceledAmount($items[$itemTransferIndex][5]);
182
            $itemTransfer->setRefundableAmount($items[$itemTransferIndex][5]);
183
        }
184
185
        $calculationFacade = $this->createCalculationFacade(
186
            [
187
                new RefundableAmountCalculatorPlugin(),
188
                new RefundTotalCalculatorPlugin(),
189
                new GrandTotalCalculatorPlugin(),
190
            ],
191
        );
192
193
        return $calculationFacade->recalculateQuote($quoteTransfer);
194
    }
195
196
    public function createDiscountTransfer(int $discountAmount, string $sku): DiscountTransfer
197
    {
198
        $voucherEntity = $this->createDiscounts($discountAmount, DiscountDependencyProvider::PLUGIN_CALCULATOR_FIXED, $sku);
199
200
        return (new DiscountTransfer())
201
            ->setVoucherCode($voucherEntity->getCode());
202
    }
203
204
    public function getCurrentStoreTransfer(): StoreTransfer
205
    {
206
        return (new StoreTransfer())
207
            ->setIdStore(1)
208
            ->setName(static::COUNTRY_DE);
209
    }
210
211
    public function getCurrentShippingAddress(): AddressTransfer
212
    {
213
        return (new AddressTransfer())->setIso2Code(static::COUNTRY_DE);
214
    }
215
216
    public function createCurrencyTransfer(): CurrencyTransfer
217
    {
218
        return (new CurrencyTransfer())
219
            ->setCode('EUR');
220
    }
221
222
    public function createItemTransfer(int $price, string $priceMode, float $taxRate, int $quantity): ItemTransfer
223
    {
224
        $abstractProductEntity = $this->createAbstractProductWithTaxSet($taxRate);
225
226
        $itemTransfer = (new ItemTransfer())
227
            ->setName('test' . $this->getIncrementNumber())
228
            ->setIdProductAbstract($abstractProductEntity->getIdProductAbstract())
229
            ->setSku('test' . $this->getIncrementNumber())
230
            ->setQuantity($quantity)
231
            ->setTaxRate($taxRate);
232
233
        if ($priceMode === CalculationPriceMode::PRICE_MODE_GROSS) {
234
            $itemTransfer->setUnitGrossPrice($price);
235
        }
236
237
        if ($priceMode === CalculationPriceMode::PRICE_MODE_NET) {
238
            $itemTransfer->setUnitNetPrice($price);
239
        }
240
241
        return $itemTransfer;
242
    }
243
244
    public function createProductOptionTransfer(int $price, string $priceMode, float $taxRate, int $quantity): ProductOptionTransfer
245
    {
246
        $productOptionValueEntity = $this->createProductOptionValue($taxRate);
247
248
        $productOptionTransfer = (new ProductOptionTransfer())
249
            ->setTaxRate($taxRate)
250
            ->setQuantity($quantity)
251
            ->setIdProductOptionValue($productOptionValueEntity->getIdProductOptionValue());
252
253
        if ($priceMode === CalculationPriceMode::PRICE_MODE_GROSS) {
254
            $productOptionTransfer->setUnitGrossPrice($price);
255
        }
256
257
        if ($priceMode === CalculationPriceMode::PRICE_MODE_NET) {
258
            $productOptionTransfer->setUnitNetPrice($price);
259
        }
260
261
        return $productOptionTransfer;
262
    }
263
264
    public function createAbstractProductWithTaxSet(float $taxRate): SpyProductAbstract
265
    {
266
        $countryEntity = SpyCountryQuery::create()->findOneByIso2Code(static::COUNTRY_DE);
267
268
        $taxRateEntity = new SpyTaxRate();
269
        $taxRateEntity->setRate($taxRate);
270
        $taxRateEntity->setName('test rate');
271
        $taxRateEntity->setFkCountry($countryEntity->getIdCountry());
272
        $taxRateEntity->save();
273
274
        $taxSetEntity = $this->createTaxSet();
275
276
        $this->createTaxSetTax($taxSetEntity, $taxRateEntity);
277
278
        return $this->createAbstractProduct($taxSetEntity);
279
    }
280
281
    public function createAbstractProductWithTaxExemption(): SpyProductAbstract
282
    {
283
        $taxRateEntity = new SpyTaxRate();
284
        $taxRateEntity->setRate(0);
285
        $taxRateEntity->setName(TaxConstants::TAX_EXEMPT_PLACEHOLDER);
286
        $taxRateEntity->save();
287
288
        $taxSetEntity = $this->createTaxSet();
289
290
        $this->createTaxSetTax($taxSetEntity, $taxRateEntity);
291
292
        return $this->createAbstractProduct($taxSetEntity);
293
    }
294
295
    protected function getIncrementNumber(): int
296
    {
297
        return ++$this->incrementNumber;
298
    }
299
300
    protected function getCurrency(): SpyCurrency
301
    {
302
        return SpyCurrencyQuery::create()->findOneByCode('EUR');
303
    }
304
305
    protected function createProductOptionValue(float $taxRate): SpyProductOptionValue
306
    {
307
        $countryEntity = SpyCountryQuery::create()->findOneByIso2Code('DE');
308
309
        $taxRateEntity = new SpyTaxRate();
310
        $taxRateEntity->setRate($taxRate);
311
        $taxRateEntity->setName('test rate');
312
        $taxRateEntity->setFkCountry($countryEntity->getIdCountry());
313
        $taxRateEntity->save();
314
315
        $taxSetEntity = $this->createTaxSet();
316
        $this->createTaxSetTax($taxSetEntity, $taxRateEntity);
317
318
        $productOptionGroupEntity = new SpyProductOptionGroup();
319
        $productOptionGroupEntity->setName('group.name.translation.key.edit');
320
        $productOptionGroupEntity->setFkTaxSet($taxSetEntity->getIdTaxSet());
321
        $productOptionGroupEntity->save();
322
323
        $productOptionValueEntity = new SpyProductOptionValue();
324
        $productOptionValueEntity->setSku('product-' . $this->getIncrementNumber());
325
        $productOptionValueEntity->setFkProductOptionGroup($productOptionGroupEntity->getIdProductOptionGroup());
326
        $productOptionValueEntity->setValue('product.option.test');
327
        $productOptionValueEntity->save();
328
329
        return $productOptionValueEntity;
330
    }
331
332
    protected function createTaxSet(): SpyTaxSet
333
    {
334
        $taxSetEntity = new SpyTaxSet();
335
        $taxSetEntity->setName('name of tax set');
336
        $taxSetEntity->save();
337
338
        return $taxSetEntity;
339
    }
340
341
    protected function createTaxSetTax(SpyTaxSet $taxSetEntity, SpyTaxRate $taxRateEntity): void
342
    {
343
        $taxSetTaxRateEntity = new SpyTaxSetTax();
344
        $taxSetTaxRateEntity->setFkTaxSet($taxSetEntity->getIdTaxSet());
345
        $taxSetTaxRateEntity->setFkTaxRate($taxRateEntity->getIdTaxRate());
346
347
        $taxSetTaxRateEntity->save();
348
    }
349
350
    protected function createAbstractProduct(SpyTaxSet $taxSetEntity): SpyProductAbstract
351
    {
352
        $abstractProductEntity = new SpyProductAbstract();
353
        $abstractProductEntity->setSku('test-abstract-sku_' . $this->getIncrementNumber());
354
        $abstractProductEntity->setAttributes('');
355
        $abstractProductEntity->setFkTaxSet($taxSetEntity->getIdTaxSet());
356
        $abstractProductEntity->save();
357
358
        return $abstractProductEntity;
359
    }
360
361
    protected function isCanceledAmount(array $items): bool
362
    {
363
        foreach ($items as $item) {
364
            if ($item[5]) {
365
                return true;
366
            }
367
        }
368
369
        return false;
370
    }
371
}
372