Passed
Pull Request — master (#67)
by
unknown
13:46
created

BillingContext::enumPrice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 8
dl 0
loc 5
rs 10
c 1
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * PHP Billing Library
4
 *
5
 * @link      https://github.com/hiqdev/php-billing
6
 * @package   php-billing
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2017-2020, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hiqdev\php\billing\tests\behat\bootstrap;
12
13
use Behat\Gherkin\Node\TableNode;
14
use BehatExpectException\ExpectException;
15
use DateTimeImmutable;
16
use hiqdev\php\billing\bill\BillInterface;
17
use hiqdev\php\billing\charge\ChargeInterface;
18
use PHPUnit\Framework\Assert;
19
20
class BillingContext extends BaseContext
21
{
22
    use ExpectException {
23
        mayFail as protected;
24
        shouldFail as protected;
25
        assertCaughtExceptionMatches as protected;
26
    }
27
28
    protected $saleTime;
29
30
    protected $bill;
31
32
    protected $charges = [];
33
34
    protected array $progressivePrice = [];
35
36
    /**
37
     * @Given reseller :reseller
38
     */
39
    public function reseller($reseller)
40
    {
41
        $this->builder->buildReseller($reseller);
42
    }
43
44
    /**
45
     * @Given customer :customer
46
     */
47
    public function customer($customer)
48
    {
49
        $this->builder->buildCustomer($customer);
50
    }
51
52
    /**
53
     * @Given manager :manager
54
     */
55
    public function manager($manager)
56
    {
57
        $this->builder->buildManager($manager);
0 ignored issues
show
Bug introduced by
The method buildManager() does not exist on hiqdev\php\billing\tests...tstrap\BuilderInterface. ( Ignorable by Annotation )

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

57
        $this->builder->/** @scrutinizer ignore-call */ 
58
                        buildManager($manager);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
58
    }
59
60
    /**
61
     * @Given /^(\S+ )?(\S+) tariff plan (\S+)/
62
     */
63
    public function plan($prefix, $type, $plan)
64
    {
65
        $prefix = strtr($prefix, ' ', '_');
66
        $grouping = $prefix === 'grouping_';
67
        $type = $grouping ? $type : $prefix.$type;
68
        $this->builder->buildPlan($plan, $type, $grouping);
69
    }
70
71
    protected function fullPrice(array $data)
72
    {
73
        if (!empty($data['price'])) {
74
            $data['rate'] = $data['price'];
75
        }
76
        $this->builder->buildPrice($data);
77
    }
78
79
    /**
80
     * @Given /price for (\S+) is +(\S+) (\S+) per (\S+) for target (.+)$/
81
     */
82
    public function priceWithTarget($type, $price, $currency, $unit, $target)
83
    {
84
        return $this->fullPrice(compact('type', 'price', 'currency', 'unit', 'target'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...cy', 'unit', 'target')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
85
    }
86
87
    /**
88
     * @Given /price for (\S+) is +(\S+) (\S+) per (\S+) prepaid (\S+)$/
89
     */
90
    public function priceWithPrepaid($type, $price, $currency, $unit, $prepaid)
91
    {
92
        return $this->fullPrice(compact('type', 'price', 'currency', 'unit', 'prepaid'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...y', 'unit', 'prepaid')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
93
    }
94
95
    /**
96
     * @Given /price for (\S+) is +(\S+) (\S+) per (\S+) prepaid (\S+) for target (\S+)$/
97
     */
98
    public function priceWithPrepaidAndTarget($type, $price, $currency, $unit, $prepaid, $target)
99
    {
100
        return $this->fullPrice(compact('type', 'price', 'currency', 'unit', 'prepaid', 'target'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact..., 'prepaid', 'target')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
101
    }
102
103
    /**
104
     * @Given /price for (\S+) is +(\S+) (\S+) per (\S+)$/
105
     */
106
    public function price($type, $price, $currency, $unit)
107
    {
108
        return $this->fullPrice(compact('type', 'price', 'currency', 'unit'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...', 'currency', 'unit')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
109
    }
110
111
    /**
112
     * @Given /price for (\S+) is +(\S+) (\S+) per 1 (\S+) and (\S+) (\S+) per 2 (\S+) for target (\S+)/
113
     */
114
    public function enumPrice($type, $price, $currency, $unit, $price2, $currency2, $unit2, $target)
0 ignored issues
show
Unused Code introduced by
The parameter $currency2 is not used and could be removed. ( Ignorable by Annotation )

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

114
    public function enumPrice($type, $price, $currency, $unit, $price2, /** @scrutinizer ignore-unused */ $currency2, $unit2, $target)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $unit2 is not used and could be removed. ( Ignorable by Annotation )

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

114
    public function enumPrice($type, $price, $currency, $unit, $price2, $currency2, /** @scrutinizer ignore-unused */ $unit2, $target)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
115
    {
116
        $sums = [1 => $price, 2 => $price2];
117
118
        return $this->fullPrice(compact('type', 'sums', 'currency', 'unit', 'target'));
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->fullPrice(compact...cy', 'unit', 'target')) targeting hiqdev\php\billing\tests...ingContext::fullPrice() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
119
    }
120
121
    /**
122
     * @Given /progressive price for (\S+) is +(\S+) (\S+) per (\S+) (\S+) (\S+) (\S+)$/
123
     */
124
    public function progressivePrice($type, $price, $currency, $unit, $sign, $quantity, $perUnit): void
0 ignored issues
show
Unused Code introduced by
The parameter $perUnit is not used and could be removed. ( Ignorable by Annotation )

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

124
    public function progressivePrice($type, $price, $currency, $unit, $sign, $quantity, /** @scrutinizer ignore-unused */ $perUnit): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $sign is not used and could be removed. ( Ignorable by Annotation )

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

124
    public function progressivePrice($type, $price, $currency, $unit, /** @scrutinizer ignore-unused */ $sign, $quantity, $perUnit): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
125
    {
126
        if (empty($this->progressivePrice[$type])) {
127
            $this->progressivePrice[$type] = [
128
                'price' => 0,
129
                'currency' => $currency,
130
                'unit' => $unit,
131
                'thresholds' =>[
132
                    [
133
                        'price' => $price,
134
                        'currency' => $currency,
135
                        'value' => $quantity,
136
                    ],
137
                ] ,
138
            ];
139
        } else {
140
            array_push(
141
                $this->progressivePrice[$type]['thresholds'],
142
                [
143
                    'price' => $price,
144
                    'currency' => $currency,
145
                    'value' => $quantity,
146
                ]
147
            );
148
        }
149
    }
150
151
    /**
152
     * @Given /^create progressive price/
153
     */
154
    public function createProgressivePrices()
155
    {
156
        foreach ($this->progressivePrice as $type => $price) {
157
            $this->fullPrice([
158
                'type' => $type,
159
                'price' => 0,
160
                'currency' => $price['currency'],
161
                'unit' => $price['unit'],
162
                'data' => ['thresholds' => $price['thresholds'], 'class' => 'progressive'],
163
            ]);
164
        }
165
    }
166
167
    /**
168
     * @Given /^remove and recreate tariff plan (\S+)/
169
     */
170
    public function recreatePlan($plan)
171
    {
172
        $this->builder->recreatePlan($plan);
173
    }
174
175
    /**
176
     * @Given /sale target (\S+) by plan (\S+) at (\S+)/
177
     */
178
    public function sale($target, $plan, $time): void
179
    {
180
        $this->saleTime = $this->prepareTime($time);
181
        $this->builder->buildSale($target, $plan, $this->saleTime);
0 ignored issues
show
Bug introduced by
It seems like $this->saleTime can also be of type null; however, parameter $time of hiqdev\php\billing\tests...rInterface::buildSale() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

181
        $this->builder->buildSale($target, $plan, /** @scrutinizer ignore-type */ $this->saleTime);
Loading history...
182
    }
183
    /**
184
     * @When /^sale close is requested for target "([^"]*)" at "([^"]*)", assuming current time is "([^"]*)"$/
185
     */
186
    public function saleClose(string $target, string $time, ?string $wallTime)
0 ignored issues
show
Unused Code introduced by
The parameter $wallTime is not used and could be removed. ( Ignorable by Annotation )

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

186
    public function saleClose(string $target, string $time, /** @scrutinizer ignore-unused */ ?string $wallTime)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $time is not used and could be removed. ( Ignorable by Annotation )

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

186
    public function saleClose(string $target, /** @scrutinizer ignore-unused */ string $time, ?string $wallTime)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $target is not used and could be removed. ( Ignorable by Annotation )

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

186
    public function saleClose(/** @scrutinizer ignore-unused */ string $target, string $time, ?string $wallTime)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
187
    {
188
        throw new PendingException();
0 ignored issues
show
Bug introduced by
The type hiqdev\php\billing\tests...tstrap\PendingException 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...
189
    }
190
191
    /**
192
     * @Then /^target "([^"]*)" has exactly (\d+) sale for customer$/
193
     */
194
    public function targetHasExactlyNSaleForCustomer(string $target, string $count)
0 ignored issues
show
Unused Code introduced by
The parameter $target is not used and could be removed. ( Ignorable by Annotation )

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

194
    public function targetHasExactlyNSaleForCustomer(/** @scrutinizer ignore-unused */ string $target, string $count)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
195
    {
196
        // TODO: implement
197
        // $sales = $this->builder->findSales(['target-name' => $target]);
198
199
        Assert::assertCount($count, $sales);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $sales seems to be never defined.
Loading history...
Bug introduced by
$count of type string is incompatible with the type integer expected by parameter $expectedCount of PHPUnit\Framework\Assert::assertCount(). ( Ignorable by Annotation )

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

199
        Assert::assertCount(/** @scrutinizer ignore-type */ $count, $sales);
Loading history...
200
    }
201
202
    /**
203
     * @Given /purchase target (\S+) by plan (\S+) at ([-:\w\s]+)$/
204
     */
205
    public function purchaseTarget(string $target, string $plan, string $time): void
206
    {
207
        $time = $this->prepareTime($time);
208
        $this->builder->buildPurchase($target, $plan, $time);
209
    }
210
211
    /**
212
     * @Given /^purchase target "([^"]*)" by plan "([^"]*)" at "([^"]*)" with the following initial uses:$/
213
     */
214
    public function purchaseTargetWithInitialUses(string $target, string $plan, string $time, TableNode $usesTable): void
215
    {
216
        $time = $this->prepareTime($time);
217
        $uses = array_map(static function (array $row) {
218
            return [
219
                'type' => $row['type'],
220
                'unit' => $row['unit'],
221
                'amount' => $row['amount'],
222
            ];
223
        }, $usesTable->getColumnsHash());
224
225
        $this->mayFail(
226
            fn() => $this->builder->buildPurchase($target, $plan, $time, $uses)
227
        );
228
    }
229
230
    /**
231
     * @Given /resource consumption for (\S+) is +(\S+) (\S+) for target (\S+) at (.+)$/
232
     */
233
    public function setConsumption(string $type, int $amount, string $unit, string $target, string $time): void
234
    {
235
        $time = $this->prepareTime($time);
236
        $this->builder->setConsumption($type, $amount, $unit, $target, $time);
0 ignored issues
show
Bug introduced by
The method setConsumption() does not exist on hiqdev\php\billing\tests...tstrap\BuilderInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to hiqdev\php\billing\tests...tstrap\BuilderInterface. ( Ignorable by Annotation )

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

236
        $this->builder->/** @scrutinizer ignore-call */ 
237
                        setConsumption($type, $amount, $unit, $target, $time);
Loading history...
237
    }
238
239
    /**
240
     * @Given /recalculate autotariff for target (\S+)( +at (\S+))?$/
241
     */
242
    public function recalculateAutoTariff(string $target, string $time = null): void
243
    {
244
        $this->builder->clientSetAutoTariff($target, $time);
0 ignored issues
show
Bug introduced by
The method clientSetAutoTariff() does not exist on hiqdev\php\billing\tests...tstrap\BuilderInterface. ( Ignorable by Annotation )

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

244
        $this->builder->/** @scrutinizer ignore-call */ 
245
                        clientSetAutoTariff($target, $time);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
245
    }
246
247
    /**
248
     * @Given /perform billing at (\S+)/
249
     */
250
    public function performBilling(string $time): void
251
    {
252
        $this->builder->performBilling($this->prepareTime($time));
253
    }
254
255
    /**
256
     * @Given /action for (\S+) is +(\S+) (\S+) +for target (.+?)( +at (\S+))?$/
257
     */
258
    public function setAction(string $type, int $amount, string $unit, string $target, string $at = null, string $time = null): void
0 ignored issues
show
Unused Code introduced by
The parameter $at is not used and could be removed. ( Ignorable by Annotation )

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

258
    public function setAction(string $type, int $amount, string $unit, string $target, /** @scrutinizer ignore-unused */ string $at = null, string $time = null): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
259
    {
260
        $time = $this->prepareTime($time);
261
        $this->builder->setAction($type, $amount, $unit, $target, $time);
0 ignored issues
show
Bug introduced by
It seems like $time can also be of type null; however, parameter $time of hiqdev\php\billing\tests...rInterface::setAction() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

261
        $this->builder->setAction($type, $amount, $unit, $target, /** @scrutinizer ignore-type */ $time);
Loading history...
262
    }
263
264
    /**
265
     * @Given /perform calculation( at (\S+))?/
266
     */
267
    public function performCalculation(string $at = null, string $time = null): array
0 ignored issues
show
Unused Code introduced by
The parameter $at is not used and could be removed. ( Ignorable by Annotation )

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

267
    public function performCalculation(/** @scrutinizer ignore-unused */ string $at = null, string $time = null): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
268
    {
269
        $this->charges = $this->builder->performCalculation($this->prepareTime($time));
0 ignored issues
show
Bug introduced by
It seems like $this->prepareTime($time) can also be of type null; however, parameter $time of hiqdev\php\billing\tests...e::performCalculation() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

269
        $this->charges = $this->builder->performCalculation(/** @scrutinizer ignore-type */ $this->prepareTime($time));
Loading history...
270
        return $this->charges;
271
    }
272
273
    /**
274
     * @Given /bill +for (\S+) is +(\S+) (\S+) per (\S+) (\S+) for target (.+?)( +at (.+))?$/
275
     */
276
    public function billWithTime($type, $sum, $currency, $quantity, $unit, $target, $at = null, $time = null)
0 ignored issues
show
Unused Code introduced by
The parameter $at is not used and could be removed. ( Ignorable by Annotation )

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

276
    public function billWithTime($type, $sum, $currency, $quantity, $unit, $target, /** @scrutinizer ignore-unused */ $at = null, $time = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
277
    {
278
        $this->builder->flushEntitiesCacheByType('bill');
279
280
        $quantity = $this->prepareQuantity($quantity);
281
        $sum = $this->prepareSum($sum, $quantity);
282
        $time = $this->prepareTime($time);
283
        $bill = $this->findBill([
284
            'type' => $type,
285
            'target' => $target,
286
            'sum' => "$sum $currency",
287
            'quantity' => "$quantity $unit",
288
            'time' => $time,
289
        ]);
290
        Assert::assertSame($type, $bill->getType()->getName(), "Bill type mismatch: expected $type, got {$bill->getType()->getName()}");
291
        Assert::assertSame($target, $bill->getTarget()->getFullName(), "Bill target mismatch: expected $target, got {$bill->getTarget()->getFullName()}");
292
        Assert::assertEquals(bcmul($sum, 100), $bill->getSum()->getAmount(), "Bill sum mismatch: expected $sum, got {$bill->getSum()->getAmount()}");
293
        Assert::assertSame($currency, $bill->getSum()->getCurrency()->getCode(), "Bill currency mismatch: expected $currency, got {$bill->getSum()->getCurrency()->getCode()}");
294
        Assert::assertEquals((float)$quantity, (float)$bill->getQuantity()->getQuantity(), "Bill quantity mismatch: expected $quantity, got {$bill->getQuantity()->getQuantity()}");
295
        Assert::assertEquals(strtolower($unit), strtolower($bill->getQuantity()->getUnit()->getName()), "Bill unit mismatch: expected $unit, got {$bill->getQuantity()->getUnit()->getName()}");
296
        if ($time) {
297
            Assert::assertEquals(new DateTimeImmutable($time), $bill->getTime(), "Bill time mismatch: expected $time, got {$bill->getTime()->format(DATE_ATOM)}");
298
        }
299
    }
300
301
    public function findBill(array $params): BillInterface
302
    {
303
        $bills = $this->builder->findBills($params);
304
        $this->bill = reset($bills);
305
        $this->charges = $this->bill->getCharges();
306
307
        return $this->bill;
308
    }
309
310
    /**
311
     * @Given /bills number is (\d+) for (\S+) for target (.+?)( +at (\S+))?$/
312
     */
313
    public function billsNumberWithTime($number, $type, $target, $at = null, $time = null)
0 ignored issues
show
Unused Code introduced by
The parameter $at is not used and could be removed. ( Ignorable by Annotation )

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

313
    public function billsNumberWithTime($number, $type, $target, /** @scrutinizer ignore-unused */ $at = null, $time = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
314
    {
315
        $count = count($this->builder->findBills(array_filter([
316
            'type' => $type,
317
            'target' => $target,
318
            'time' => $this->prepareTime($time),
319
        ])));
320
321
        Assert::assertEquals($number, $count);
322
    }
323
324
    /**
325
     * @Given /charges number is (\d+)/
326
     */
327
    public function chargesNumber($number)
328
    {
329
        Assert::assertEquals($number, count($this->charges));
330
    }
331
332
    /**
333
     * @Given /charge for (\S+) is +(\S+) (\S+) per (\S+) (\S+)$/
334
     */
335
    public function charge($type, $amount, $currency, $quantity, $unit)
336
    {
337
        $this->chargeWithTarget($type, $amount, $currency, $quantity, $unit, null);
338
    }
339
340
    /**
341
     * @Given /charge for (\S+) is +(\S+) (\S+) per +(\S+) (\S+) +for target (.+?)( +at (\S+))?$/
342
     */
343
    public function chargeWithTarget($type, $amount, $currency, $quantity, $unit, $target, $at = null, $time = null)
0 ignored issues
show
Unused Code introduced by
The parameter $at is not used and could be removed. ( Ignorable by Annotation )

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

343
    public function chargeWithTarget($type, $amount, $currency, $quantity, $unit, $target, /** @scrutinizer ignore-unused */ $at = null, $time = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $time is not used and could be removed. ( Ignorable by Annotation )

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

343
    public function chargeWithTarget($type, $amount, $currency, $quantity, $unit, $target, $at = null, /** @scrutinizer ignore-unused */ $time = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
344
    {
345
        $quantity = $this->prepareQuantity($quantity);
346
        $amount = $this->prepareSum($amount, $quantity);
347
        $charge = $this->findCharge($type, $target);
348
        Assert::assertNotNull($charge);
349
        Assert::assertSame($type, $charge->getType()->getName());
350
        Assert::assertSame($target, $charge->getTarget()->getFullName());
351
        Assert::assertEquals(bcmul($amount, 100), (int)$charge->getSum()->getAmount());
352
        Assert::assertSame($currency, $charge->getSum()->getCurrency()->getCode());
353
        Assert::assertEquals((float)$quantity, (float)$charge->getUsage()->getQuantity());
354
        Assert::assertEquals(strtolower($unit), strtolower($charge->getUsage()->getUnit()->getName()));
355
    }
356
357
    public function findCharge($type, $target): ?ChargeInterface
358
    {
359
        foreach ($this->charges as $charge) {
360
            if ($charge->getType()->getName() !== $type) {
361
                continue;
362
            }
363
            if ($charge->getTarget()->getFullName() !== $target) {
364
                continue;
365
            }
366
367
            return $charge;
368
        }
369
370
        return null;
371
    }
372
373
    public function getNextCharge(): ChargeInterface
374
    {
375
        $charge = current($this->charges);
376
        next($this->charges);
377
378
        return $charge;
379
    }
380
381
    /**
382
     * @return string|false|null
383
     */
384
    protected function prepareTime(string $time = null)
385
    {
386
        if ($time === null) {
387
            return null;
388
        }
389
390
        if ($time === 'midnight second day of this month') {
391
            return date('Y-m-02');
392
        }
393
        if (strncmp($time, 'pY', 1) === 0) {
394
            return date(substr($time, 1), strtotime('-1 year'));
395
        }
396
        if (str_contains($time, 'nm')) {
397
            $format = str_replace('nm', 'm', $time);
398
            return date($format, strtotime('next month'));
399
        }
400
        if (str_contains($time, 'pm')) {
401
            $time = str_replace('pm', 'm', $time);
402
            $time = date($time, strtotime('-1 month'));
403
        }
404
        if (strncmp($time, 'Y', 1) === 0) {
405
            return date($time);
406
        }
407
408
        return $time;
409
    }
410
411
    private function prepareQuantity($quantity)
412
    {
413
        if ($quantity[0] === 's') {
414
            return $this->getSaleQuantity();
415
        }
416
417
        return $quantity;
418
    }
419
420
    private function prepareSum($sum, $quantity)
421
    {
422
        if ($sum[0] === 's') {
423
            $sum = round(substr($sum, 1) * $quantity*100)/100;
424
        }
425
426
        return $sum;
427
    }
428
429
    public function getSaleQuantity()
430
    {
431
        return $this->days2quantity(new DateTimeImmutable($this->saleTime));
432
    }
433
434
    private function days2quantity(DateTimeImmutable $from)
435
    {
436
        $till = new DateTimeImmutable('first day of next month midnight');
437
        $diff = $from->diff($till);
438
        if ($diff->m) {
439
            return 1;
440
        }
441
442
        return $diff->d/date('t');
443
    }
444
445
    /**
446
     * @When /^tariff plan change is requested for target "([^"]*)" to plan "([^"]*)" at "([^"]*)"$/
447
     */
448
    public function tariffPlanChangeIsRequestedForTarget(string $target, string $planName, string $date)
449
    {
450
        $this->mayFail(fn () => $this->builder->targetChangePlan($target, $planName, $this->prepareTime($date)));
451
    }
452
453
    /**
454
     * @When /^tariff plan change is requested for target "([^"]*)" to plan "([^"]*)" at "([^"]*)", assuming current time is "([^"]*)"$/
455
     */
456
    public function tariffPlanChangeIsRequestedForTargetAtSpecificTime(string $target, string $planName, string $date, ?string $wallTime = null)
457
    {
458
        $this->mayFail(fn () => $this->builder->targetChangePlan($target, $planName, $this->prepareTime($date), $this->prepareTime($wallTime)));
459
    }
460
461
    /**
462
     * @Then /^target "([^"]*)" is sold to customer by plan "([^"]*)" since "([^"]*)"(?: till "([^"]*)")?$/
463
     */
464
    public function targetIsSoldToCustomerByPlanSinceTill(string $target, string $planName, string $saleDate, ?string $saleCloseDate = null)
465
    {
466
        $sales = $this->builder->findHistoricalSales([
467
            'target' => $target,
468
        ]);
469
470
        $saleDateTime = new DateTimeImmutable('@' . strtotime($this->prepareTime($saleDate)));
471
        $saleCloseDateTime = $saleCloseDate ? new DateTimeImmutable('@' . strtotime($this->prepareTime($saleCloseDate))) : null;
472
473
        foreach ($sales as $sale) {
474
            /** @noinspection PhpBooleanCanBeSimplifiedInspection */
475
            $saleExists = true
476
                && str_contains($sale->getPlan()->getName(), $planName)
477
                && $sale->getTime()->format(DATE_ATOM) === $saleDateTime->format(DATE_ATOM)
478
                && (
479
                    ($saleCloseDate === null && $sale->getCloseTime() === null)
480
                    ||
481
                    ($saleCloseDate !== null && $sale->getCloseTime()->format(DATE_ATOM) === $saleCloseDateTime->format(DATE_ATOM))
482
                );
483
484
            if ($saleExists) {
485
                return;
486
            }
487
        }
488
489
        Assert::fail('Requested sale does not exist');
490
    }
491
492
    /**
493
     * @Then /^target "([^"]*)" has exactly (\d+) sales for customer$/
494
     */
495
    public function targetHasExactlySalesForCustomer(string $target, int $count)
496
    {
497
        $sales = $this->builder->findHistoricalSales([
498
            'target' => $target,
499
        ]);
500
501
        Assert::assertCount($count, $sales);
502
    }
503
504
    /**
505
     * @Then /^caught error is "([^"]*)"$/
506
     */
507
    public function caughtErrorIs(string $errorMessage): void
508
    {
509
        $this->assertCaughtExceptionMatches(\Throwable::class, $errorMessage);
510
    }
511
512
    /**
513
     * @Given /^target "([^"]*)"$/
514
     */
515
    public function target(string $target)
516
    {
517
        $this->builder->buildTarget($target);
518
    }
519
520
    /**
521
     * @Then /^flush entities cache$/
522
     */
523
    public function flushEntitiesCache()
524
    {
525
        $this->builder->flushEntitiesCache();
526
    }
527
528
    /**
529
     * @Given /^target "([^"]*)" has the following uses:$/
530
     */
531
    public function targetHasTheFollowingUses(string $target, TableNode $usesTable)
532
    {
533
        foreach ($usesTable->getColumnsHash() as $row) {
534
            $uses = $this->builder->findUsage($row['time'], $target, $row['type']);
535
            Assert::assertCount(1, $uses);
536
537
            $use = reset($uses);
538
            Assert::assertSame(
539
                $row['unit'], $use['unit'],
540
                sprintf('Exptected unit to be %s, got %s instead', $row['unit'], $use['unit'])
541
            );
542
            Assert::assertEquals(
543
                $row['amount'], $use['total'],
544
                sprintf('Exptected total to be %s, got %s instead', $row['amount'], $use['total'])
545
            );
546
        }
547
    }
548
}
549