Passed
Pull Request — master (#69)
by Dmitry
10:38
created

ProgressivePriceTest::setUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace hiqdev\php\billing\tests\unit\price;
6
7
use Generator;
8
use hiqdev\php\billing\price\ProgressivePrice;
9
use hiqdev\php\billing\price\ProgressivePriceThresholds;
10
use hiqdev\php\billing\target\Target;
11
use hiqdev\php\billing\type\Type;
12
use hiqdev\php\units\Quantity;
13
use Money\Currencies\ISOCurrencies;
14
use Money\Currency;
15
use Money\Parser\DecimalMoneyParser;
16
use PHPUnit\Framework\TestCase;
17
18
19
class ProgressivePriceTest extends TestCase
20
{
21
    private Quantity $usage;
22
    private DecimalMoneyParser $moneyParser;
23
24
    protected function setUp(): void
25
    {
26
        parent::setUp();
27
28
        $this->usage = Quantity::mbps(720);
29
        $this->moneyParser = new DecimalMoneyParser(new ISOCurrencies());
30
    }
31
32
    private function createProgressivePrice(string $prepaid, string $startPrice, array $thresholdsArray): ProgressivePrice
33
    {
34
        $type = new Type('2222', 'cdn_traf95_max');
35
        $target = new Target('2222', 'overuse,cdn_traf95_max', 'ProgressivePrice');
36
        $prepaid = Quantity::mbps($prepaid);
37
        $money = $this->moneyParser->parse($startPrice, new Currency('EUR'));
38
        $thresholds = ProgressivePriceThresholds::fromScalarsArray($thresholdsArray);
39
40
        return new ProgressivePrice('2222', $type, $target, $prepaid, $money, $thresholds);
41
    }
42
43
    /** @dataProvider progressivePriceProvider */
44
    public function testProgressivePriceCalculation(
45
        array $thresholdsArray,
46
        int $expectedAmount,
47
        string $startPrice,
48
        string $prepaid = '0'
49
    ): void {
50
        $price = $this->createProgressivePrice(
51
            prepaid: $prepaid,
52
            startPrice: $startPrice,
53
            thresholdsArray: $thresholdsArray
54
        );
55
56
        $usage = $price->calculateUsage($this->usage);
57
        $this->assertSame($this->usage->getQuantity(), $usage->getQuantity());
58
59
        $amount = $price->calculateSum($this->usage);
60
        $this->assertEquals($expectedAmount, $amount->getAmount());
61
    }
62
63
    /**
64
     * @dataProvider progressivePriceProvider
65
     */
66
    public function testProgressivePriceSerialization(
67
        array $inputThresholdsArray,
68
        int $expectedAmount,
0 ignored issues
show
Unused Code introduced by
The parameter $expectedAmount 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

68
        /** @scrutinizer ignore-unused */ int $expectedAmount,

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...
69
        string $startPrice,
70
        string $prepaid = '0'
71
    ): void {
72
        $price = $this->createProgressivePrice(
73
            prepaid: $prepaid,
74
            startPrice: $startPrice,
75
            thresholdsArray: $inputThresholdsArray
76
        );
77
78
        $unserialized = json_decode(json_encode($price), true);
79
        $this->assertArrayHasKey('id', $unserialized);
80
        $this->assertArrayHasKey('type', $unserialized);
81
        $this->assertArrayHasKey('target', $unserialized);
82
        $this->assertArrayHasKey('thresholds', $unserialized);
83
        $this->assertArrayHasKey('price', $unserialized);
84
        $this->assertArrayHasKey('prepaid', $unserialized);
85
86
        $this->assertSame($price->getId(), $unserialized['id']);
87
88
        $this->assertSame($price->getType()->getId(), $unserialized['type']['id']);
89
        $this->assertSame($price->getType()->getName(), $unserialized['type']['name']);
90
91
        $this->assertSame($price->getTarget()->getId(), $unserialized['target']['id']);
92
        $this->assertSame($price->getTarget()->getType(), $unserialized['target']['type']);
93
        $this->assertSame($price->getTarget()->getName(), $unserialized['target']['name']);
94
95
        $this->assertSame($price->getPrice()->getAmount(), $unserialized['price']['amount']);
96
        $this->assertSame($price->getPrice()->getCurrency()->getCode(), $unserialized['price']['currency']);
97
98
        $this->assertSame($price->getPrepaid()->getQuantity(), $unserialized['prepaid']['quantity']);
99
        $this->assertSame($price->getPrepaid()->getUnit()->getName(), $unserialized['prepaid']['unit']);
100
101
        $thresholdsArray = $price->getThresholds()->get();
102
        $unserializedThresholds = array_reverse($unserialized['thresholds']);
103
        $this->assertCount(count($inputThresholdsArray), $unserializedThresholds);
104
        foreach ($thresholdsArray as $index => $threshold) {
105
            $val = (new \ReflectionObject($threshold))->getProperty('price')->getValue($threshold);
106
            $this->assertSame($val, $unserializedThresholds[$index]['price']);
107
            $this->assertSame($threshold->price()->getCurrency()->getCode(), $unserializedThresholds[$index]['currency']);
108
            $this->assertSame($threshold->quantity()->getQuantity(), $unserializedThresholds[$index]['quantity']);
109
            $this->assertSame($threshold->quantity()->getUnit()->getName(), $unserializedThresholds[$index]['unit']);
110
        }
111
    }
112
113
    private function progressivePriceProvider(): Generator
0 ignored issues
show
Unused Code introduced by
The method progressivePriceProvider() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
114
    {
115
        yield 'Simple case' => [
116
            'thresholds' => [
117
                ['price' => '0.0085', 'currency' => 'EUR', 'quantity' => '0', 'unit' => 'mbps'],
118
                ['price' => '0.0080', 'currency' => 'EUR', 'quantity' => '500', 'unit' => 'mbps'],
119
                ['price' => '0.0075', 'currency' => 'EUR', 'quantity' => '600', 'unit' => 'mbps'],
120
                ['price' => '0.0070', 'currency' => 'EUR', 'quantity' => '700', 'unit' => 'mbps'],
121
                ['price' => '0.0065', 'currency' => 'EUR', 'quantity' => '800', 'unit' => 'mbps'],
122
            ],
123
            'money' => 594,
124
            'price' => '0.0085',
125
        ];
126
127
       yield 'Different prices for the same quantity – take higher price' => [
128
            'thresholds' => [
129
                ['price' => '6', 'currency' => 'EUR', 'quantity' => '0', 'unit' => 'mbps'],
130
                ['price' => '4', 'currency' => 'EUR', 'quantity' => '100', 'unit' => 'mbps'], // Here the qty is the same
131
                ['price' => '5', 'currency' => 'EUR', 'quantity' => '0.1', 'unit' => 'gbps'], // as here, despite units are different
132
                ['price' => '3', 'currency' => 'EUR', 'quantity' => '200', 'unit' => 'mbps'],
133
            ],
134
            'money' => 266000,
135
            'price' => '6',
136
137
            // 100mbps * 6 = 600
138
            // 100mbps * 5 = 500
139
            // 520mbps * 3 = 1560
140
            //             = 2660
141
        ];
142
143
        yield 'Bill without prepaid amount' => [
144
            'thresholds' => [
145
                ['price' => '6', 'currency' => 'EUR', 'quantity' => '100', 'unit' => 'mbps'],
146
                ['price' => '5', 'currency' => 'EUR', 'quantity' => '200', 'unit' => 'mbps'],
147
                ['price' => '4', 'currency' => 'EUR', 'quantity' => '300', 'unit' => 'mbps'],
148
                ['price' => '3', 'currency' => 'EUR', 'quantity' => '400', 'unit' => 'mbps'],
149
            ],
150
            'money' => 306000,
151
            'price' => '6',
152
            'prepaid' => '0',
153
154
            //   100mbps * 6 = 600 // No prepaid, fully billed
155
            // + 100mbps * 6 = 600
156
            // + 100mbps * 5 = 500
157
            // + 100mbps * 4 = 400
158
            // + 320mbps * 3 = 960
159
            // = 720mbps     = 3060
160
        ];
161
162
        yield 'Bill with prepaid amount' => [
163
            'thresholds' => [
164
                ['price' => '1', 'currency' => 'EUR', 'quantity' => '20', 'unit' => 'mbps'],
165
                ['price' => '0.9', 'currency' => 'EUR', 'quantity' => '30', 'unit' => 'mbps'],
166
                ['price' => '0.856', 'currency' => 'EUR', 'quantity' => '0.1', 'unit' => 'gbps'],
167
                ['price' => '0.5521', 'currency' => 'EUR', 'quantity' => '130.5', 'unit' => 'mbps'],
168
            ],
169
            'result' => 43487,
170
            'price' => '1.03',
171
            'prepaid' => '10',
172
173
            // TOTAL consumption 720mbps
174
            //   10mbps * 0         = 0   // prepaid, not billable
175
            // + 10mbps * 1.03      = 10.3
176
            // + 10mbps * 1         = 10
177
            // + 70mbps * 0.90      = 63
178
            // + 30.5mbps * 0.856   = 26.11
179
            // + 589.5mbps * 0.5521 = 325.46
180
            //                      = 434.87
181
            // Total billed 710mbps
182
        ];
183
    }
184
}
185