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

ProgressivePrice   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 11
eloc 28
c 1
b 0
f 0
dl 0
loc 82
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getThresholds() 0 3 1
A prepareThresholds() 0 5 1
A calculatePrice() 0 18 4
A __construct() 0 11 1
A getPrepaid() 0 3 1
A calculateUsage() 0 9 2
A calculateSum() 0 3 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\Currency;
13
use Money\Money;
14
15
class ProgressivePrice extends AbstractPrice
16
{
17
    /* @var ProgressivePriceConditionDto[] $thresholds */
18
    protected array $thresholds;
19
    /**
20
     * @var QuantityInterface prepaid quantity also implies Unit
21
     * XXX cannot be null cause Unit is required
22
     */
23
    protected $prepaid;
24
25
    public function __construct(
26
        $id,
27
        TypeInterface $type,
28
        TargetInterface $target,
29
        QuantityInterface $prepaid,
30
        array $thresholds,
31
        ?PlanInterface $plan = null
32
    ) {
33
        parent::__construct($id, $type, $target, $plan);
34
        $this->prepaid = $prepaid;
35
        $this->thresholds = $thresholds;
36
    }
37
38
    public function getPrepaid()
39
    {
40
        return $this->prepaid;
41
    }
42
43
    public function getThresholds(): array
44
    {
45
        return $this->thresholds;
46
    }
47
48
    private function prepareThresholds(): void
49
    {
50
        usort($this->thresholds, function($a, $b)
51
            {
52
                return $b->value <=> $a->value;
53
            }
54
        );
55
    }
56
57
    /**
58
     * @inheritDoc
59
     */
60
    public function calculateUsage(QuantityInterface $quantity): ?QuantityInterface
61
    {
62
        $usage = $quantity->convert($this->prepaid->getUnit())->subtract($this->prepaid);
63
64
        if ($usage->isPositive()) {
65
            return $usage;
66
        }
67
68
        return Quantity::create($this->prepaid->getUnit()->getName(), 0);
69
    }
70
71
    /**
72
     * @inheritDoc
73
     */
74
    public function calculatePrice(QuantityInterface $quantity): ?Money
75
    {
76
        $result = null;
77
        $this->prepareThresholds();
78
        $usage = $this->calculateUsage($quantity);
79
        $quantity = $usage->getQuantity();
80
        foreach ($this->thresholds as $key => $threshold) {
81
            if  ($threshold->value < $quantity) {
82
                if ($key !== count($this->thresholds) - 1) {
83
                    $boundary = $quantity - $threshold->value;
84
                    $result += $boundary * $threshold->price;
85
                    $quantity = $quantity - $boundary;
86
                } else {
87
                    $result += $quantity * $threshold->price;
88
                }
89
            }
90
        }
91
        return new Money((int)($result * 100), $threshold->currency);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $threshold seems to be defined by a foreach iteration on line 80. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
92
    }
93
94
    public function calculateSum(QuantityInterface $quantity): ?Money
95
    {
96
        return $this->calculatePrice($quantity);
97
    }
98
}
99