Account::afterFind()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace app\core\models;
4
5
use app\core\exceptions\InvalidArgumentException;
6
use app\core\services\AccountService;
7
use app\core\services\TransactionService;
8
use app\core\types\AccountStatus;
9
use app\core\types\AccountType;
10
use app\core\types\ColorType;
11
use app\core\types\CurrencyCode;
12
use Yii;
13
use yii\behaviors\TimestampBehavior;
14
use yiier\helpers\DateHelper;
15
use yiier\helpers\Setup;
16
use yiier\validators\MoneyValidator;
17
18
/**
19
 * This is the model class for table "{{%account}}".
20
 *
21
 * @property int $id
22
 * @property int $user_id
23
 * @property string $name
24
 * @property int|string $type
25
 * @property string $color
26
 * @property int|null $balance_cent
27
 * @property int|null $currency_balance_cent
28
 * @property string $currency_code
29
 * @property int|string $status
30
 * @property int|null $exclude_from_stats
31
 * @property int|null $credit_card_limit
32
 * @property int|null $credit_card_repayment_day
33
 * @property int|null $credit_card_billing_day
34
 * @property int $default
35
 * @property int|null $sort
36
 * @property string|null $created_at
37
 * @property string|null $updated_at
38
 *
39
 * @property-read User $user
40
 *
41
 */
42
class Account extends \yii\db\ActiveRecord
43
{
44
    public const DEFAULT = 1;
45
    public const NO_DEFAULT = 0;
46
    public $balance;
47
    public $currency_balance;
48
49
    public const SCENARIO_CREDIT_CARD = 'credit_card';
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public static function tableName()
55
    {
56
        return '{{%account}}';
57
    }
58
59
    public function transactions()
60
    {
61
        return [
62
            self::SCENARIO_DEFAULT => self::OP_INSERT | self::OP_UPDATE | self::OP_DELETE,
63
            self::SCENARIO_CREDIT_CARD => self::OP_INSERT | self::OP_UPDATE | self::OP_DELETE,
64
        ];
65
    }
66
67
    /**
68
     * @inheritdoc
69
     * @throws \yii\base\InvalidConfigException
70
     */
71
    public function behaviors()
72
    {
73
        return [
74
            [
75
                'class' => TimestampBehavior::class,
76
                'value' => Yii::$app->formatter->asDatetime('now')
77
            ],
78
        ];
79
    }
80
81
    /**
82
     * {@inheritdoc}
83
     */
84
    public function rules()
85
    {
86
        return [
87
            [['user_id', 'name', 'type', 'currency_balance', 'currency_code', 'default'], 'required'],
88
            [
89
                ['credit_card_limit', 'credit_card_repayment_day', 'credit_card_billing_day'],
90
                'required',
91
                'on' => self::SCENARIO_CREDIT_CARD
92
            ],
93
            [
94
                [
95
                    'user_id',
96
                    'balance_cent',
97
                    'currency_balance_cent',
98
                    'credit_card_limit',
99
                    'credit_card_repayment_day',
100
                    'credit_card_billing_day',
101
                    'sort',
102
                ],
103
                'integer'
104
            ],
105
            ['status', 'in', 'range' => AccountStatus::names()],
106
            [['name'], 'string', 'max' => 120],
107
            [['color'], 'string', 'max' => 7],
108
            ['type', 'in', 'range' => AccountType::names()],
109
            [['balance', 'currency_balance'], MoneyValidator::class, 'allowsNegative' => true], //todo message
110
            ['exclude_from_stats', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true],
111
            ['default', 'boolean', 'trueValue' => true, 'falseValue' => false, 'strict' => true],
112
            ['currency_code', 'in', 'range' => CurrencyCode::getKeys()],
113
            [
114
                'name',
115
                'unique',
116
                'targetAttribute' => ['user_id', 'name'],
117
                'message' => Yii::t('app', 'The {attribute} has been used.')
118
            ],
119
        ];
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function attributeLabels()
126
    {
127
        return [
128
            'id' => Yii::t('app', 'ID'),
129
            'user_id' => Yii::t('app', 'User ID'),
130
            'name' => Yii::t('app', 'Name'),
131
            'type' => Yii::t('app', 'Type'),
132
            'color' => Yii::t('app', 'Color'),
133
            'balance' => Yii::t('app', 'Balance'),
134
            'balance_cent' => Yii::t('app', 'Balance Cent'),
135
            'currency_code' => Yii::t('app', 'Currency Code'),
136
            'status' => Yii::t('app', 'Status'),
137
            'exclude_from_stats' => Yii::t('app', 'Exclude From Stats'),
138
            'credit_card_limit' => Yii::t('app', 'Credit Card Limit'),
139
            'credit_card_repayment_day' => Yii::t('app', 'Credit Card Repayment Day'),
140
            'credit_card_billing_day' => Yii::t('app', 'Credit Card Billing Day'),
141
            'default' => Yii::t('app', 'Default'),
142
            'sort' => Yii::t('app', 'Sort'),
143
            'created_at' => Yii::t('app', 'Created At'),
144
            'updated_at' => Yii::t('app', 'Updated At'),
145
        ];
146
    }
147
148
    /**
149
     */
150
    public function afterFind()
151
    {
152
        parent::afterFind();
153
    }
154
155
156
    /**
157
     * @param bool $insert
158
     * @return bool
159
     * @throws InvalidArgumentException|\Throwable
160
     */
161
    public function beforeSave($insert)
162
    {
163
        if (parent::beforeSave($insert)) {
164
            if ($insert) {
165
                $ran = ColorType::items();
166
                $this->color = $this->color ?: $ran[mt_rand(0, count($ran) - 1)];
167
            }
168
            $this->status = is_null($this->status) ? AccountStatus::ACTIVE : AccountStatus::toEnumValue($this->status);
0 ignored issues
show
introduced by
The condition is_null($this->status) is always false.
Loading history...
169
            $this->currency_balance_cent = Setup::toFen($this->currency_balance);
170
            if ($this->currency_code == $this->user->base_currency_code) {
171
                $this->balance_cent = $this->currency_balance_cent;
172
            } else {
173
                // $this->balance_cent = $this->currency_balance_cent;
174
                // todo 计算汇率
175
            }
176
177
            $this->type = AccountType::toEnumValue($this->type);
178
            return true;
179
        } else {
180
            return false;
181
        }
182
    }
183
184
    public function getUser()
185
    {
186
        return $this->hasOne(User::class, ['id' => 'user_id']);
187
    }
188
189
    /**
190
     * @param bool $insert
191
     * @param array $changedAttributes
192
     * @throws \yii\db\Exception
193
     * @throws \Exception
194
     */
195
    public function afterSave($insert, $changedAttributes)
196
    {
197
        parent::afterSave($insert, $changedAttributes);
198
        if (data_get($changedAttributes, 'currency_balance_cent') !== $this->currency_balance_cent) {
199
            TransactionService::createAdjustRecord($this);
200
        }
201
        if ($this->default) {
202
            Account::updateAll(
203
                ['default' => self::NO_DEFAULT, 'updated_at' => Yii::$app->formatter->asDatetime('now')],
204
                ['and', ['user_id' => $this->user_id, 'default' => self::DEFAULT], ['!=', 'id', $this->id]]
205
            );
206
        }
207
    }
208
209
    public function afterDelete()
210
    {
211
        parent::afterDelete();
212
        AccountService::afterDelete($this);
213
    }
214
215
    /**
216
     * @return array
217
     */
218
    public function fields()
219
    {
220
        $fields = parent::fields();
221
        unset($fields['currency_balance_cent'], $fields['balance_cent'], $fields['user_id']);
222
223
        $fields['type'] = function (self $model) {
224
            return AccountType::getName($model->type);
0 ignored issues
show
Bug introduced by
It seems like $model->type can also be of type string; however, parameter $v of app\core\types\BaseType::getName() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

224
            return AccountType::getName(/** @scrutinizer ignore-type */ $model->type);
Loading history...
225
        };
226
227
        $fields['status'] = function (self $model) {
228
            return AccountStatus::getName($model->status);
0 ignored issues
show
Bug introduced by
It seems like $model->status can also be of type string; however, parameter $v of app\core\types\BaseType::getName() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

228
            return AccountStatus::getName(/** @scrutinizer ignore-type */ $model->status);
Loading history...
229
        };
230
231
        $fields['icon_name'] = function (self $model) {
232
            return AccountType::getName($model->type);
0 ignored issues
show
Bug introduced by
It seems like $model->type can also be of type string; however, parameter $v of app\core\types\BaseType::getName() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

232
            return AccountType::getName(/** @scrutinizer ignore-type */ $model->type);
Loading history...
233
        };
234
235
        $fields['type_name'] = function (self $model) {
236
            return data_get(AccountType::texts(), $model->type);
237
        };
238
239
        $fields['balance'] = function (self $model) {
240
            return Setup::toYuan($model->balance_cent);
241
        };
242
243
        $fields['currency_balance'] = function (self $model) {
244
            return Setup::toYuan($model->currency_balance_cent);
245
        };
246
247
        $fields['default'] = function (self $model) {
248
            return (bool)$model->default;
249
        };
250
251
        $fields['exclude_from_stats'] = function (self $model) {
252
            return (bool)$model->exclude_from_stats;
253
        };
254
255
        $fields['created_at'] = function (self $model) {
256
            return DateHelper::datetimeToIso8601($model->created_at);
0 ignored issues
show
Bug introduced by
It seems like $model->created_at can also be of type null; however, parameter $dateStr of yiier\helpers\DateHelper::datetimeToIso8601() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

256
            return DateHelper::datetimeToIso8601(/** @scrutinizer ignore-type */ $model->created_at);
Loading history...
257
        };
258
259
        $fields['updated_at'] = function (self $model) {
260
            return DateHelper::datetimeToIso8601($model->updated_at);
0 ignored issues
show
Bug introduced by
It seems like $model->updated_at can also be of type null; however, parameter $dateStr of yiier\helpers\DateHelper::datetimeToIso8601() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

260
            return DateHelper::datetimeToIso8601(/** @scrutinizer ignore-type */ $model->updated_at);
Loading history...
261
        };
262
263
        return $fields;
264
    }
265
}
266