Passed
Push — master ( e39bb0...54e3cc )
by Dmitry
14:48
created

ProgressivePrice::calculateUsage()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace hiqdev\php\billing\price;
6
7
use hiqdev\php\billing\plan\PlanInterface;
8
use hiqdev\php\billing\target\TargetInterface;
9
use hiqdev\php\billing\type\TypeInterface;
10
use hiqdev\php\units\Quantity;
11
use hiqdev\php\units\QuantityInterface;
12
use Money\Currencies\ISOCurrencies;
13
use Money\Currency;
14
use Money\Money;
15
use Money\Parser\DecimalMoneyParser;
16
17
class ProgressivePrice extends AbstractPrice
18
{
19
    protected ProgressivePriceThresholds $thresholds;
20
21
    protected Money $price;
22
23
    protected QuantityInterface $prepaid;
24
25
    public function __construct(
26
        $id,
27
        TypeInterface $type,
28
        TargetInterface $target,
29
        QuantityInterface $prepaid,
30
        Money $price,
31
        /* @psalm-var array{
32
         *     array{
33
         *         'price': string,
34
         *         'currency': string,
35
         *         'quantity': string,
36
         *         'unit': string
37
         *     }
38
         * } $thresholds
39
         */
40
        array $thresholds,
41
        ?PlanInterface $plan = null
42
    ) {
43
        parent::__construct($id, $type, $target, $plan);
44
        $this->thresholds = new ProgressivePriceThresholds($thresholds);
45
        $this->price = $price;
46
        $this->prepaid = $prepaid;
47
    }
48
49
    public function getThresholds(): array
50
    {
51
        return $this->thresholds->__toArray();
52
    }
53
54
    public function getPrepaid(): QuantityInterface
55
    {
56
        return $this->prepaid;
57
    }
58
59
    public function getPrice(): Money
60
    {
61
        return $this->price;
62
    }
63
64
    /**
65
     * @inheritDoc
66
     */
67
    public function calculateUsage(QuantityInterface $quantity): ?QuantityInterface
68
    {
69
        $usage = $quantity->convert($this->prepaid->getUnit());
70
71
        if ($usage->isPositive()) {
72
            return $usage;
73
        }
74
75
        return Quantity::create($this->prepaid->getUnit()->getName(), 0);
76
    }
77
78
    /**
79
     * @inheritDoc
80
     */
81
    public function calculatePrice(QuantityInterface $quantity): ?Money
82
    {
83
        return $this->price;
84
    }
85
86
    public function calculateSum(QuantityInterface $quantity): ?Money
87
    {
88
        $result = new Money(0, $this->price->getCurrency());
89
        $usage = $this->calculateUsage($quantity);
90
        $thresholds = $this->thresholds->get();
91
        foreach ($thresholds as $key => $threshold) {
92
            if  ($threshold->quantity()->compare($usage) < 0) {
93
                    $boundary = $usage->subtract($threshold->quantity());
94
                    $result = $result->add(new Money(
95
                            (int) $boundary->multiply($threshold->price()->getAmount())->getQuantity(),
96
                            $threshold->price()->getCurrency()
97
                        )
98
                    );
99
                    $usage = $usage->subtract($boundary);
100
            }
101
        }
102
        $result = (new DecimalMoneyParser(new ISOCurrencies()))->parse($result->getAmount(), $result->getCurrency());
103
        return $result->divide($this->thresholds->getPriceRate());
104
    }
105
}
106