Completed
Push — master ( c6b5de...db50e7 )
by Dmitry
04:45
created

src/forms/BillForm.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\forms;
12
13
use hipanel\modules\finance\behaviors\BillQuantity;
14
use hipanel\modules\finance\logic\bill\QuantityTrait;
15
use hipanel\modules\finance\models\Bill;
16
use hipanel\modules\finance\models\Charge;
17
use hipanel\modules\finance\models\Currency;
18
use hipanel\modules\finance\validation\BillChargesSumValidator;
19
use Yii;
20
use yii\base\Model;
21
22
class BillForm extends Model
23
{
24
    use QuantityTrait;
25
26
    const SCENARIO_CREATE = 'create';
27
    const SCENARIO_UPDATE = 'update';
28
    const SCENARIO_COPY   = 'copy';
29
30
    const EVENT_SHOW_FORM = 'showForm';
31
32
    /**
33
     * @var integer
34
     */
35
    public $id;
36
37
    /**
38
     * @var integer
39
     */
40
    public $client_id;
41
42
    /**
43
     * @var string
44
     */
45
    public $currency;
46
47
    /**
48
     * @var float
49
     */
50
    public $sum;
51
52
    /**
53
     * @var string
54
     */
55
    public $time;
56
57
    /**
58
     * @var string
59
     */
60
    public $type;
61
62
    /**
63
     * @var string
64
     */
65
    public $gtype;
66
67
    /**
68
     * @var float
69
     */
70
    public $quantity;
71
72
    /**
73
     * @var float
74
     */
75
    public $unit;
76
77
    /**
78
     * @var float
79
     */
80
    public $userQuantity;
81
82
    /**
83
     * @var string
84
     */
85
    public $label;
86
87
    /**
88
     * @var integer
89
     */
90
    public $object_id;
91
92
    /**
93
     * @var string
94
     */
95
    public $object;
96
97
    /**
98
     * @var string
99
     */
100
    public $class;
101
102
    /**
103
     * @var Charge[]
104
     */
105
    public $charges = [];
106
107
    public function behaviors()
108
    {
109
        return [
110
            [
111
                'class' => BillQuantity::class,
112
            ],
113
        ];
114
    }
115
116
    /**
117
     * Creates [[BillForm]] from [[Bill]].
118
     *
119
     * @param Bill $bill
120
     * @param string $scenario
121
     * @return BillForm
122
     */
123
    public static function createFromBill($bill, $scenario)
124
    {
125
        $attributes = $bill->getAttributes([
126
            'id', 'object_id', 'client_id', 'currency', 'type',
127
            'gtype', 'sum', 'time', 'quantity', 'unit', 'label', 'object', 'class',
128
        ]);
129
130
        $form = new self(['scenario' => $scenario]);
131
        $form->setAttributes($attributes, false);
132
133
        $form->charges = array_map(function ($model) use ($scenario) {
134
            $model->scenario = $scenario;
135
136
            return $model;
137
        }, $bill->charges);
138
139
        return $form;
140
    }
141
142
    /**
143
     * @param Bill[] $bills
144
     * @param string $scenario
145
     * @return BillForm[]
146
     */
147
    public static function createMultipleFromBills($bills, $scenario)
148
    {
149
        $result = [];
150
        foreach ($bills as $bill) {
151
            $result[] = self::createFromBill($bill, $scenario);
152
        }
153
154
        return $result;
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160
    public function load($data, $formName = null)
161
    {
162
        $this->setAttributes($data);
163
        $this->loadCharges($data['charges']);
164
165
        return true;
166
    }
167
168
    /**
169
     * @return Charge[]
170
     */
171
    public function getCharges()
172
    {
173
        if (!empty($this->charges)) {
174
            return $this->charges;
175
        }
176
177
        return [$this->newCharge()];
178
    }
179
180
    /**
181
     * Creates new charge.
182
     *
183
     * @return Charge
184
     */
185
    public function newCharge()
186
    {
187
        return new Charge(['scenario' => Charge::SCENARIO_CREATE]);
188
    }
189
190
    /**
191
     * @return array
192
     */
193
    public function rules()
194
    {
195
        return [
196
            [['id', 'object_id'], 'integer', 'on' => [self::SCENARIO_UPDATE]],
197
            [['sum', 'quantity'], 'number', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]],
198
            [['time'], 'date', 'format' => 'php:Y-m-d H:i:s'],
199
            [['label', 'currency', 'unit', 'type', 'object', 'class'], 'safe', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]],
200
            [['sum'], BillChargesSumValidator::class],
201
            [['unit'], 'default', 'value' => 'items', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]], // TODO: should be probably replaced with input on client side
202
            [['object_id'], 'integer', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]],
203
            [['currency'], function ($attribute) {
204
                if (!array_key_exists(mb_strtolower($this->{$attribute}), array_change_key_case(Currency::list(), CASE_LOWER))) {
205
                    $this->addError($attribute, Yii::t('hipanel:finance', 'Currency is invalid'));
206
                }
207
            }, 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY],
208
            ],
209
            [['id'], 'required', 'on' => [self::SCENARIO_UPDATE]],
210
            [
211
                ['client_id', 'sum', 'quantity', 'unit', 'time', 'currency', 'type'],
212
                'required',
213
                'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY],
214
            ],
215
            [['!charges'], 'safe', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]],
216
217
            [['time', 'object_id', 'type'], function ($attribute) {
218
                try {
219
                    Bill::perform('check-unique', $this->attributes);
220
                } catch (\Exception $e) {
221
                    $this->addError($attribute, Yii::t('hipanel:finance', 'The bill is not unique'));
222
                }
223
            }, 'on' => self::SCENARIO_COPY],
224
        ];
225
    }
226
227
    public function attributeLabels()
228
    {
229
        return [
230
            'client_id' => Yii::t('hipanel', 'Client'),
231
            'time' => Yii::t('hipanel', 'Time'),
232
            'currency' => Yii::t('hipanel', 'Currency'),
233
            'sum' => Yii::t('hipanel:finance', 'Sum'),
234
            'label' => Yii::t('hipanel', 'Description'),
235
            'type' => Yii::t('hipanel', 'Type'),
236
            'quantity' => Yii::t('hipanel', 'Quantity'),
237
            'object_id' => Yii::t('hipanel', 'Object'),
238
        ];
239
    }
240
241
    public function getIsNewRecord()
242
    {
243
        return $this->id === null;
244
    }
245
246
    public function forceNewRecord(): void
247
    {
248
        $this->id = null;
249
        $this->time = new \DateTime();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \DateTime() of type object<DateTime> is incompatible with the declared type string of property $time.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
250
    }
251
252
    private function getChargesAsArray()
253
    {
254
        return array_filter(array_map(function ($model) {
255
            /** @var Charge $model */
256
            if ($model->validate()) {
257
                return $model->toArray();
258
            }
259
260
            return null;
261
        }, $this->charges));
262
    }
263
264
    public function fields()
265
    {
266
        return [
267
            'id',
268
            'client_id',
269
            'object_id',
270
            'currency',
271
            'sum',
272
            'time',
273
            'type',
274
            'quantity',
275
            'label',
276
            'object',
277
            'class',
278
            'charges' => function () {
279
                return $this->getChargesAsArray();
280
            },
281
        ];
282
    }
283
284
    public function loadCharges($data)
285
    {
286
        $charges = [];
287
288
        foreach ((array) $data as $datum) {
289
            $charge = $this->newCharge();
290
            if ($charge->load($datum, '')) {
291
                $charge->markAsNotNew();
292
                $charges[] = $charge;
293
            }
294
        }
295
296
        $this->charges = $charges;
297
298
        return true;
299
    }
300
301
    public function getPrimaryKey()
302
    {
303
        return $this->id;
304
    }
305
306
    public static function primaryKey()
307
    {
308
        return ['id'];
309
    }
310
311
    /**
312
     * For compatibility with [[hiqdev\hiart\Collection]].
313
     *
314
     * @param $defaultScenario
315
     * @param array $data
316
     * @param array $options
317
     * @return mixed
318
     */
319
    public function batchQuery($defaultScenario, $data = [], array $options = [])
320
    {
321
        $map = [
322
            'create' => 'create',
323
            'update' => 'update',
324
        ];
325
        $scenario = isset($map[$defaultScenario]) ? $map[$defaultScenario] : $defaultScenario;
326
327
        return (new Bill())->batchQuery($scenario, $data, $options);
328
    }
329
330
    public function getOldAttribute($attribute)
331
    {
332
        return $this->$attribute;
333
    }
334
335
    public function setOldAttribute($attribute, $value)
336
    {
337
        return true;
338
    }
339
340
    public function setOldAttributes($values)
341
    {
342
        return true;
343
    }
344
345
    public function afterSave()
346
    {
347
        return true;
348
    }
349
}
350