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

BillingContext::progressivePrice()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
c 0
b 0
f 0
dl 0
loc 22
rs 9.7666
cc 2
nc 2
nop 7
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