Completed
Push — master ( d2bc6c...36fb8b )
by Andrii
06:47
created

PriceChargesEstimator::groupCalculationsByTarget()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 43
ccs 0
cts 33
cp 0
rs 8.9208
c 0
b 0
f 0
cc 5
nc 7
nop 0
crap 30
1
<?php
2
3
namespace hipanel\modules\finance\helpers;
4
5
use hipanel\modules\finance\widgets\PriceChargesEstimationTable;
6
use Money\Currencies\ISOCurrencies;
7
use Money\Currency;
8
use Money\Formatter\DecimalMoneyFormatter;
9
use Money\Money;
10
use Yii;
11
12
/**
13
 * Class PriceChargesEstimator
14
 *
15
 * @author Dmytro Naumenko <[email protected]>
16
 */
17
class PriceChargesEstimator
18
{
19
    /**
20
     * @var \yii\i18n\Formatter
21
     */
22
    protected $yiiFormatter;
23
    /**
24
     * @var DecimalMoneyFormatter
25
     */
26
    protected $moneyFormatter;
27
    /**
28
     * @var array
29
     */
30
    protected $calculations = [];
31
32
    /**
33
     * @var string[] array of strings compatible with `strtotime()`, e.g. `first day of next month`
34
     */
35
    private $periods = [];
36
37
    public function __construct(array $calculations)
38
    {
39
        $this->calculations = $calculations;
40
        $this->yiiFormatter = Yii::$app->formatter;
41
        $this->moneyFormatter = new DecimalMoneyFormatter(new ISOCurrencies());
42
    }
43
44
    public function __invoke($periods)
45
    {
46
        $this->calculateForPeriods($periods);
47
    }
48
49
    /**
50
     * @var string[] array of strings compatible with `strtotime()`, e.g. `first day of next month`
51
     * @return array
52
     */
53
    public function calculateForPeriods($periods): array
54
    {
55
        $this->periods = $periods;
56
57
        return $this->groupCalculationsByTarget();
58
    }
59
60
    private function groupCalculationsByTarget()
61
    {
62
        $result = [];
63
64
        foreach ($this->calculations as $period => $charges) {
65
            $chargesByTargetAndAction = [];
66
67
            foreach ($charges as $charge) {
68
                $action = $charge['action'];
69
70
                $targetId = $action['target']['id'];
71
                $actionType = $action['type']['name'];
72
                $priceType = $charge['price']['type']['name'];
73
                $sum = $charge['sum'];
74
75
                $money = new Money($sum['amount'], new Currency($sum['currency']));
76
                $price = $this->moneyFormatter->format($money);
77
78
                $chargesByTargetAndAction['targets'][$targetId][$actionType]['charges'][] = [
79
                    'type' => $priceType,
80
                    'price' => $price,
81
                    'currency' => $sum['currency'],
82
                    'comment' => $charge['comment'],
83
                    'formattedPrice' => $this->yiiFormatter->asCurrency($price, $sum['currency']),
84
                ];
85
86
                $chargesByTargetAndAction['sum'] += $price;
87
                $chargesByTargetAndAction['sumFormatted'] = $this->yiiFormatter->asCurrency($chargesByTargetAndAction['sum'], $sum['currency']);
88
            }
89
            unset($action);
90
91
            foreach ($chargesByTargetAndAction['targets'] as &$actions) {
92
                foreach ($actions as &$action) {
93
                    $this->decorateAction($action);
94
                }
95
            }
96
            unset($action, $actions);
97
98
            $result[$this->yiiFormatter->asDate(strtotime($period), 'php:M Y')] = $chargesByTargetAndAction;
99
        }
100
101
        return $result;
102
    }
103
104
    private function decorateAction(&$action)
105
    {
106
        $action['sum'] = array_sum(array_column($action['charges'], 'price'));
107
        $action['sumFormatted'] = $this->yiiFormatter->asCurrency($action['sum'],
108
            reset($action['charges'])['currency']);
109
        $action['detailsTable'] = PriceChargesEstimationTable::widget(['charges' => $action['charges']]);
110
    }
111
}
112