Passed
Push — master ( 413f2b...47fb92 )
by Sylvain
09:09
created

AccountRepository::totalBalanceByParent()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 29
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.8846

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 1
dl 0
loc 29
ccs 7
cts 13
cp 0.5385
crap 3.8846
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Repository;
6
7
use Application\DBAL\Types\AccountTypeType;
8
use Application\Model\Account;
9
use Application\Model\User;
10
11
class AccountRepository extends AbstractRepository implements LimitedAccessSubQueryInterface
12
{
13
    private const PARENT_ACCOUNT_ID_FOR_USER = 10011;
14
    const ACCOUNT_ID_FOR_BANK = 10025;
15
16
    /**
17
     * Returns pure SQL to get ID of all objects that are accessible to given user.
18
     *
19
     * @param null|User $user
20
     *
21
     * @return string
22
     */
23 11
    public function getAccessibleSubQuery(?User $user): string
24
    {
25 11
        if (!$user) {
26 1
            return '-1';
27
        }
28
29 10
        if (in_array($user->getRole(), [User::ROLE_RESPONSIBLE, User::ROLE_ADMINISTRATOR], true)) {
30 2
            return $this->getAllIdsQuery();
31
        }
32
33 8
        return $this->getAllIdsForOwnerQuery($user);
34
    }
35
36
    /**
37
     * Unsecured way to get a account from its ID.
38
     *
39
     * This should only be used in tests or controlled environment.
40
     *
41
     * @param int $id
42
     *
43
     * @return null|Account
44
     */
45 8
    private function getOneById(int $id): ?Account
46
    {
47 8
        $this->getAclFilter()->setEnabled(false);
48 8
        $account = $this->findOneById($id);
49 8
        $this->getAclFilter()->setEnabled(true);
50
51 8
        return $account;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $account could return the type Application\Model\AbstractModel which includes types incompatible with the type-hinted return Application\Model\Account|null. Consider adding an additional type-check to rule them out.
Loading history...
52
    }
53
54
    /**
55
     * This will return, and potentially create, an account for the given user
56
     *
57
     * @param User $user
58
     *
59
     * @return Account
60
     */
61 16
    public function getOrCreate(User $user): Account
62
    {
63
        // If an account already exists, because getOrCreate was called once before without flushing in between,
64
        // then can return immediately
65 16
        if ($user->getAccount()) {
66 11
            return $user->getAccount();
67
        }
68
69 8
        $this->getAclFilter()->setEnabled(false);
70 8
        $account = $this->findOneByOwner($user);
0 ignored issues
show
Bug introduced by
The method findOneByOwner() does not exist on Application\Repository\AccountRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

70
        /** @scrutinizer ignore-call */ 
71
        $account = $this->findOneByOwner($user);
Loading history...
71 8
        $this->getAclFilter()->setEnabled(true);
72
73 8
        if (!$account) {
74 8
            $account = new Account();
75 8
            $this->getEntityManager()->persist($account);
76 8
            $account->setOwner($user);
77 8
            $account->setType(AccountTypeType::LIABILITY);
78 8
            $account->setName($user->getName());
79
80 8
            $maxCode = $this->getEntityManager()->getConnection()->fetchColumn('SELECT MAX(code) FROM account WHERE parent_id = ' . self::PARENT_ACCOUNT_ID_FOR_USER);
81 8
            $newCode = ++$maxCode;
82 8
            $account->setCode((string) $newCode);
83
84 8
            $parent = $this->getOneById(self::PARENT_ACCOUNT_ID_FOR_USER);
85 8
            if (!$parent) {
86
                throw new \Exception('Cannot find parent account for creation of user account');
87
            }
88 8
            $account->setParent($parent);
89
        }
90
91 8
        return $account;
92
    }
93
94
    /**
95
     * Sum balance by account type
96
     *
97
     * @API\Input(type="AccountType")
98
     *
99
     * @param string $accountType
100
     *
101
     * @return string
102
     */
103 1
    public function totalBalanceByType(string $accountType): string
104
    {
105 1
        $qb = $this->getEntityManager()->getConnection()->createQueryBuilder()
106 1
            ->select('SUM(balance)')
107 1
            ->from($this->getClassMetadata()->getTableName())
108 1
            ->where('type = :type');
109
110 1
        $qb->setParameter('type', $accountType);
111
112 1
        $result = $qb->execute();
113
114 1
        return (string) $result->fetchColumn();
115
    }
116
}
117