AccountService::createUpdate()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 10
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 15
rs 9.9332
1
<?php
2
3
namespace app\core\services;
4
5
use app\core\exceptions\InternalException;
6
use app\core\models\Account;
7
use app\core\models\Record;
8
use app\core\models\Recurrence;
9
use app\core\models\Rule;
10
use app\core\models\Transaction;
11
use app\core\types\DirectionType;
12
use Exception;
13
use Yii;
14
use yii\db\ActiveRecord;
15
use yii\helpers\ArrayHelper;
16
use yiier\helpers\Setup;
17
18
class AccountService
19
{
20
    public static function afterDelete(Account $account)
21
    {
22
        $baseConditions = ['user_id' => Yii::$app->user->id];
23
        Record::deleteAll($baseConditions + ['account_id' => $account->id]);
24
25
        $transactionIds = Transaction::find()
26
            ->where([
27
                'and',
28
                $baseConditions,
29
                ['or', ['from_account_id' => $account->id], ['to_account_id' => $account->id]]
30
            ])
31
            ->column();
32
        Transaction::deleteAll($baseConditions + ['id' => $transactionIds]);
33
        Recurrence::deleteAll($baseConditions + ['transaction_id' => $transactionIds]);
34
35
        Rule::deleteAll([
36
            'and',
37
            $baseConditions,
38
            ['or', ['then_from_account_id' => $account->id], ['then_to_account_id' => $account->id]]
39
        ]);
40
    }
41
42
    /**
43
     * @param Account $account
44
     * @return Account
45
     * @throws InternalException
46
     */
47
    public function createUpdate(Account $account): Account
48
    {
49
        try {
50
            $account->user_id = Yii::$app->user->id;
0 ignored issues
show
Documentation Bug introduced by
It seems like Yii::app->user->id can also be of type string. However, the property $user_id is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
51
            if (!$account->save()) {
52
                throw new \yii\db\Exception(Setup::errorMessage($account->firstErrors));
53
            }
54
        } catch (Exception $e) {
55
            Yii::error(
56
                ['request_id' => Yii::$app->requestId->id, $account->attributes, $account->errors, (string)$e],
57
                __FUNCTION__
58
            );
59
            throw new InternalException($e->getMessage());
60
        }
61
        return Account::findOne($account->id);
0 ignored issues
show
Bug Best Practice introduced by
The expression return app\core\models\A...::findOne($account->id) returns the type yii\db\ActiveRecord which includes types incompatible with the type-hinted return app\core\models\Account.
Loading history...
62
    }
63
64
65
    /**
66
     * @param int $id
67
     * @return Account|ActiveRecord|null
68
     */
69
    public static function findCurrentOne(int $id)
70
    {
71
        return Account::find()->where(['id' => $id])
0 ignored issues
show
Bug Best Practice introduced by
The expression return app\core\models\A...:app->user->id))->one() also could return the type array which is incompatible with the documented return type app\core\models\Account|null|yii\db\ActiveRecord.
Loading history...
72
            ->andWhere(['user_id' => Yii::$app->user->id])
73
            ->one();
74
    }
75
76
    public static function getDefaultAccount(int $userId = 0)
77
    {
78
        $userId = $userId ?: Yii::$app->user->id;
79
        return Account::find()
80
            ->where(['user_id' => $userId, 'default' => Account::DEFAULT])
81
            ->orderBy(['id' => SORT_ASC])
82
            ->asArray()
83
            ->one();
84
    }
85
86
    /**
87
     * @param int $accountId
88
     * @return bool
89
     * @throws \yii\db\Exception
90
     */
91
    public static function updateAccountBalance(int $accountId): bool
92
    {
93
        if (!$model = self::findCurrentOne($accountId)) {
94
            throw new \yii\db\Exception('not found account');
95
        }
96
        $model->load($model->toArray(), '');
97
        $model->currency_balance = Setup::toYuan(self::getCalculateCurrencyBalanceCent($accountId));
98
        if (!$model->save()) {
99
            Yii::error(
100
                ['request_id' => Yii::$app->requestId->id, $model->attributes, $model->errors],
101
                __FUNCTION__
102
            );
103
            throw new \yii\db\Exception('update account failure ' . Setup::errorMessage($model->firstErrors));
104
        }
105
        return true;
106
    }
107
108
109
    /**
110
     * @param int $accountId
111
     * @return int
112
     */
113
    public static function getCalculateCurrencyBalanceCent(int $accountId): int
114
    {
115
        $in = Record::find()->where([
116
            'account_id' => $accountId,
117
            'direction' => DirectionType::INCOME,
118
        ])->sum('currency_amount_cent');
119
120
        $out = Record::find()->where([
121
            'account_id' => $accountId,
122
            'direction' => DirectionType::EXPENSE,
123
        ])->sum('currency_amount_cent');
124
125
        return ($in - $out) ?: 0;
126
    }
127
128
    /**
129
     * @return array
130
     */
131
    public static function getCurrentMap()
132
    {
133
        $accounts = Account::find()->where(['user_id' => Yii::$app->user->id])->asArray()->all();
134
        return ArrayHelper::map($accounts, 'id', 'name');
135
    }
136
}
137