Completed
Push — master ( 4b3a6a...ccebfa )
by Dmitry
04:39
created

Price   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 20
lcom 3
cbo 8
dl 0
loc 181
ccs 0
cts 128
cp 0
rs 10
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A rules() 0 17 1
A attributeLabels() 0 13 1
A getTypeOptions() 0 8 1
A getUnitOptions() 0 37 1
A isQuantityPredefined() 0 10 4
A isShared() 0 4 1
A getUnitLabel() 0 4 1
A getCurrencyOptions() 0 4 1
A getObject() 0 4 1
A getPlan() 0 4 1
A tableName() 0 4 1
A isOveruse() 0 4 1
A getSubtype() 0 6 1
A instantiate() 0 7 1
A formulaLines() 0 8 2
A getMoney() 0 6 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\models;
12
13
use hipanel\models\Ref;
14
use hipanel\modules\finance\models\factories\PriceModelFactory;
15
use Money\Money;
16
use Money\MoneyParser;
17
use Yii;
18
use yii\helpers\Inflector;
19
use yii\helpers\StringHelper;
20
21
/**
22
 * Class Price.
23
 *
24
 * @property int $id
25
 * @property int $plan_id
26
 * @property string|int $object_id
27
 * @property string|float $price
28
 * @property string $currency
29
 * @property string|int $main_object_id
30
 * @property string $main_object_name
31
 * @property string $unit
32
 * @property string $type
33
 * @property string $quantity
34
 * @property string $formula
35
 *
36
 * @property TargetObject $object
37
 * @property Plan $plan
38
 *
39
 * @author Dmytro Naumenko <[email protected]>
40
 */
41
class Price extends \hipanel\base\Model
42
{
43
    use \hipanel\base\ModelTrait;
44
45
    const SCENARIO_CREATE = 'create';
46
    const SCENARIO_UPDATE = 'update';
47
    const SCENARIO_DELETE = 'delete';
48
49
    public function rules()
50
    {
51
        return array_merge(parent::rules(), [
52
            [['id', 'parent_id', 'plan_id', 'object_id', 'type_id', 'unit_id', 'currency_id', 'main_object_id'], 'integer'],
53
            [['type', 'type_label', 'plan_name', 'unit', 'currency', 'note', 'data', 'main_object_name'], 'string'],
54
            [['quantity', 'price'], 'number'],
55
            [['class'], 'string'], // todo: probably, refactor is needed
56
57
            [['plan_id', 'type', 'price', 'currency'], 'required', 'on' => ['create', 'update']],
58
            [['id'], 'required', 'on' => ['update', 'set-note', 'delete']],
59
            [['class'], 'default', 'value' => function ($model) {
0 ignored issues
show
Unused Code introduced by
The parameter $model is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
60
                return (new \ReflectionClass($this))->getShortName();
61
            }],
62
            [['class'], 'string'],
63
            [['formula'], 'string', 'on' => ['create', 'update']], // TODO syn check
64
        ]);
65
    }
66
67
    public function attributeLabels()
68
    {
69
        return [
70
            'plan_id' => Yii::t('hipanel:finance', 'Tariff plan'),
71
            'plan' => Yii::t('hipanel:finance', 'Tariff plan'),
72
            'quantity' => Yii::t('hipanel:finance', 'Prepaid'),
73
            'unit' => Yii::t('hipanel:finance', 'Unit'),
74
            'price' => Yii::t('hipanel:finance', 'Price'),
75
            'formula' => Yii::t('hipanel.finance.price', 'Formula'),
76
            'note' => Yii::t('hipanel', 'Note'),
77
            'type' => Yii::t('hipanel', 'Type'),
78
        ];
79
    }
80
81
    public function getTypeOptions()
82
    {
83
        return Ref::getList('type,bill', null, [
84
            'select' => 'name',
85
            'pnames' => 'monthly,overuse',
86
            'with_recursive' => 1,
87
        ]);
88
    }
89
90
    /**
91
     * Returns array of unit option, that are available for this price
92
     * depending on price type.
93
     *
94
     * @return array
95
     */
96
    public function getUnitOptions()
97
    {
98
        $unitGroup = [
99
            'speed' => ['bps', 'kbps', 'mbps', 'gbps', 'tbps'],
100
            'size' => ['mb', 'mb10', 'mb100', 'gb', 'tb'],
101
        ];
102
103
        $availableUnitsByPriceType = [
104
            'overuse,ip_num' => ['items'],
105
            'overuse,support_time' => ['hour'],
106
            'overuse,backup_du' => $unitGroup['size'],
107
            'overuse,server_traf_max' => $unitGroup['size'],
108
            'overuse,server_traf95_max' => $unitGroup['speed'],
109
            'overuse,server_du' => $unitGroup['size'],
110
            'overuse,server_ssd' => $unitGroup['size'],
111
            'overuse,server_sata' => $unitGroup['size'],
112
            'overuse,backup_traf' => $unitGroup['size'],
113
            'overuse,domain_traf' => $unitGroup['size'],
114
            'overuse,domain_num' => ['items'],
115
            'overuse,ip_traf_max' => $unitGroup['size'],
116
            'overuse,account_traf' => $unitGroup['size'],
117
            'overuse,account_du' => $unitGroup['size'],
118
            'overuse,mail_num' => ['items'],
119
            'overuse,mail_du' => $unitGroup['size'],
120
            'overuse,db_num' => ['items'],
121
        ];
122
123
        $units = Ref::getList('type,unit', 'hipanel.finance.units', [
124
            'with_recursive' => 1,
125
            'select' => 'oname_label',
126
            'mapOptions' => ['from' => 'oname'],
127
        ]);
128
129
        $possibleTypes = $availableUnitsByPriceType[$this->type] ?? [];
130
131
        return array_intersect_key($units, array_combine($possibleTypes, $possibleTypes));
132
    }
133
134
    /**
135
     * Method checks, whether current price quantity is predefined and is not a result
136
     * of sophisticated calculation on server side.
137
     * @return bool
138
     */
139
    public function isQuantityPredefined(): bool
140
    {
141
        if (!$this->isOveruse()
142
            && ($this->isShared() || $this->getSubtype() === 'rack_unit')
143
        ) {
144
            return false;
145
        }
146
147
        return true;
148
    }
149
150
    /**
151
     * @return bool Whether this price is shared
152
     */
153
    public function isShared(): bool
154
    {
155
        return $this->object_id === null;
156
    }
157
158
    public function getUnitLabel()
159
    {
160
        return $this->getUnitOptions()[$this->unit] ?? null;
161
    }
162
163
    public function getCurrencyOptions()
164
    {
165
        return Ref::getList('type,currency');
166
    }
167
168
    public function getObject()
169
    {
170
        return $this->hasOne(TargetObject::class, ['id' => 'id']);
171
    }
172
173
    public function getPlan()
174
    {
175
        return $this->hasOne(Plan::class, ['id' => 'plan_id']);
176
    }
177
178
    public static function tableName()
179
    {
180
        return Inflector::camel2id(StringHelper::basename(__CLASS__), '-');
181
    }
182
183
    public function isOveruse()
184
    {
185
        return strpos($this->type, 'overuse,') === 0;
186
    }
187
188
    public function getSubtype()
189
    {
190
        [, $subtype] = explode(',', $this->type);
0 ignored issues
show
Bug introduced by
The variable $subtype does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
191
192
        return $subtype;
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198
    public static function instantiate($row)
199
    {
200
        /** @var PriceModelFactory $factory */
201
        $factory = Yii::$container->get(PriceModelFactory::class);
202
203
        return $factory->build($row['class'] ?? 'SinglePrice', $row['type']);
204
    }
205
206
    public function formulaLines(): array
207
    {
208
        if (strlen($this->formula) === 0) {
209
            return [];
210
        }
211
212
        return explode("\n", $this->formula);
213
    }
214
215
    public function getMoney(): Money
216
    {
217
        // TODO: decide how to get MoneyParser correctly
218
        return Yii::$container->get(MoneyParser::class)
219
            ->parse((string)$this->price, strtoupper($this->currency));
220
    }
221
}
222