Issues (113)

src/price/ProgressivePrice.php (1 issue)

Labels
Severity
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;
0 ignored issues
show
The type hiqdev\php\billing\type\TypeInterface 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...
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 implements PriceWithThresholdsInterface,
18
    PriceWithMoneyInterface,
19
    PriceWithQuantityInterface
20
{
21
    use HasMoney;
22
    use HasQuantity;
23
24
    protected ProgressivePriceThresholdList $thresholds;
25
26
    public function __construct(
27
        $id,
28
        TypeInterface $type,
29
        TargetInterface $target,
30
        QuantityInterface $prepaid,
31
        Money $price,
32
        ProgressivePriceThresholdList $thresholds,
33
        ?PlanInterface $plan = null
34
    )
35
    {
36
        parent::__construct($id, $type, $target, $plan);
37
        $this->thresholds = $thresholds;
38
        $this->price = $price;
39
        $this->prepaid = $prepaid;
40
    }
41
42
    public function getThresholds(): ProgressivePriceThresholdList
43
    {
44
        return $this->thresholds;
45
    }
46
47
    /**
48
     * @inheritDoc
49
     */
50
    public function calculateUsage(QuantityInterface $quantity): ?QuantityInterface
51
    {
52
        $usage = $quantity->subtract($this->prepaid);
53
54
        if ($usage->isPositive()) {
55
            return $quantity->convert($this->prepaid->getUnit());
56
        }
57
58
        return Quantity::create($this->prepaid->getUnit()->getName(), 0);
59
    }
60
61
    /**
62
     * @inheritDoc
63
     */
64
    public function calculatePrice(QuantityInterface $quantity): ?Money
65
    {
66
        return $this->price;
67
    }
68
69
    /**
70
     * @var ProgressivePriceCalculationTrace[]
71
     */
72
    private array $calculationTraces = [];
73
74
    /**
75
     * @return ProgressivePriceCalculationTrace[]
76
     * @internal A debug method to see intermediate calculations
77
     * after the latest call to calculateSum()
78
     */
79
    public function getCalculationTraces(): array
80
    {
81
        return $this->calculationTraces;
82
    }
83
84
    public function calculateSum(QuantityInterface $quantity): ?Money
85
    {
86
        $this->calculationTraces = [];
87
88
        $result = $this->price->multiply(0);
89
        $remainingUsage = $this->calculateUsage($quantity);
90
        if ($remainingUsage->getQuantity() === 0) {
91
            return $result;
92
        }
93
94
        $totalBilledUsage = $this->prepaid;
95
        $thresholds = $this->thresholds->withAdded(
96
            ProgressivePriceThreshold::createFromObjects($this->price, $this->prepaid)
97
        )->get();
98
99
        foreach ($thresholds as $threshold) {
100
            $quantity = $threshold->quantity();
101
            if ($quantity->compare($remainingUsage) >= 0) {
102
                $quantity = $remainingUsage;
103
            }
104
            $billedUsage = $remainingUsage->subtract($quantity)->convert($threshold->unit());
105
            $price = $threshold->price();
106
107
            $chargedAmount = $price->money()
108
                                   ->multiply((string)(sprintf('%.14F', $billedUsage->getQuantity())))
109
                                   ->divide((string)(sprintf('%.14F', $price->multiplier())));
110
111
            $this->calculationTraces[] = new ProgressivePriceCalculationTrace(
112
                $threshold, $billedUsage, $chargedAmount
113
            );
114
115
            $result = $result->add($chargedAmount);
116
            $remainingUsage = $remainingUsage->subtract($billedUsage);
117
            $totalBilledUsage = $totalBilledUsage->add($billedUsage);
118
        }
119
120
        return $result;
121
    }
122
}
123