PriceChargesEstimator   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 7
dl 0
loc 101
ccs 0
cts 62
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A __invoke() 0 4 1
A calculateForPeriods() 0 6 1
B groupCalculationsByTarget() 0 49 6
A decorateAction() 0 7 1
1
<?php
2
/**
3
 * Finance module for HiPanel
4
 *
5
 * @link      https://github.com/hiqdev/hipanel-module-finance
6
 * @package   hipanel-module-finance
7
 * @license   BSD-3-Clause
8
 * @copyright Copyright (c) 2015-2019, HiQDev (http://hiqdev.com/)
9
 */
10
11
namespace hipanel\modules\finance\helpers;
12
13
use hipanel\modules\finance\widgets\PriceChargesEstimationTable;
14
use Money\Currencies\ISOCurrencies;
15
use Money\Currency;
16
use Money\Formatter\DecimalMoneyFormatter;
17
use Money\Money;
18
use Yii;
19
20
/**
21
 * Class PriceChargesEstimator.
22
 *
23
 * @author Dmytro Naumenko <[email protected]>
24
 */
25
class PriceChargesEstimator
26
{
27
    /**
28
     * @var \yii\i18n\Formatter
29
     */
30
    protected $yiiFormatter;
31
    /**
32
     * @var DecimalMoneyFormatter
33
     */
34
    protected $moneyFormatter;
35
    /**
36
     * @var array
37
     */
38
    protected $calculations = [];
39
40
    /**
41
     * @var string[] array of strings compatible with `strtotime()`, e.g. `first day of next month`
42
     */
43
    private $periods = [];
44
45
    public function __construct(array $calculations)
46
    {
47
        $this->calculations = $calculations;
48
        $this->yiiFormatter = Yii::$app->formatter;
49
        $this->moneyFormatter = new DecimalMoneyFormatter(new ISOCurrencies());
50
    }
51
52
    public function __invoke($periods)
53
    {
54
        $this->calculateForPeriods($periods);
55
    }
56
57
    /**
58
     * @var string[] array of strings compatible with `strtotime()`, e.g. `first day of next month`
59
     * @return array
60
     */
61
    public function calculateForPeriods($periods): array
62
    {
63
        $this->periods = $periods;
64
65
        return $this->groupCalculationsByTarget();
66
    }
67
68
    private function groupCalculationsByTarget()
69
    {
70
        $result = [];
71
72
        foreach ($this->calculations as $period => $charges) {
73
            $chargesByTargetAndAction = [];
74
75
            foreach ($charges as $charge) {
76
                $action = $charge['action'];
77
78
                $targetId = $action['target']['id'];
79
                $actionType = $action['type']['name'];
80
                $priceType = $charge['price']['type']['name'];
81
                $sum = $charge['sum'];
82
83
                $money = new Money($sum['amount'], new Currency($sum['currency']));
84
                $price = $this->moneyFormatter->format($money);
85
86
                $chargesByTargetAndAction['targets'][$targetId][$actionType]['charges'][] = [
87
                    'type' => $priceType,
88
                    'price' => $price,
89
                    'currency' => $sum['currency'],
90
                    'comment' => $charge['comment'],
91
                    'formattedPrice' => $this->yiiFormatter->asCurrency($price, $sum['currency']),
92
                ];
93
94
                $chargesByTargetAndAction['sum'] += $price;
95
                $chargesByTargetAndAction['targets'][$targetId][$actionType]['quantity'] = max(
96
                    $charge['action']['quantity']['quantity'],
97
                    $chargesByTargetAndAction['targets'][$targetId][$actionType]['quantity'] ?? 0
98
                );
99
                $chargesByTargetAndAction['sumFormatted'] = $this->yiiFormatter->asCurrency($chargesByTargetAndAction['sum'], $sum['currency']);
100
            }
101
            unset($action);
102
103
            if (!empty($chargesByTargetAndAction['targets'])) {
104
                foreach ($chargesByTargetAndAction['targets'] as &$actions) {
105
                    foreach ($actions as &$action) {
106
                        $this->decorateAction($action);
107
                    }
108
                }
109
            }
110
            unset($action, $actions);
111
112
            $result[$this->yiiFormatter->asDate(strtotime($period), 'php:M Y')] = $chargesByTargetAndAction;
113
        }
114
115
        return $result;
116
    }
117
118
    private function decorateAction(&$action)
119
    {
120
        $action['sum'] = array_sum(array_column($action['charges'], 'price'));
121
        $action['currency'] = reset($action['charges'])['currency'];
122
        $action['sumFormatted'] = $this->yiiFormatter->asCurrency($action['sum'], $action['currency']);
123
        $action['detailsTable'] = PriceChargesEstimationTable::widget(['charges' => $action['charges']]);
124
    }
125
}
126