Completed
Push — master ( a3944f...f16550 )
by Adrien
09:01
created

AccountRepository::getOrCreate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 17
nc 3
nop 1
dl 0
loc 28
ccs 18
cts 18
cp 1
crap 3
rs 9.7
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
     * @throws \Exception
44
     *
45
     * @return Account
46
     */
47 12
    public function getOneById(int $id): Account
48
    {
49 12
        $this->getAclFilter()->setEnabled(false);
50 12
        $account = $this->findOneById($id);
51 12
        $this->getAclFilter()->setEnabled(true);
52 12
        if (!$account) {
53 1
            throw new \Exception('Account #' . $id . ' not found');
54
        }
55
56 12
        return $account;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $account returns the type Application\Model\AbstractModel which includes types incompatible with the type-hinted return Application\Model\Account.
Loading history...
57
    }
58
59
    /**
60
     * This will return, and potentially create, an account for the given user
61
     *
62
     * @param User $user
63
     *
64
     * @return Account
65
     */
66 16
    public function getOrCreate(User $user): Account
67
    {
68
        // If an account already exists, because getOrCreate was called once before without flushing in between,
69
        // then can return immediately
70 16
        if ($user->getAccount()) {
71 11
            return $user->getAccount();
72
        }
73
74 8
        $this->getAclFilter()->setEnabled(false);
75 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

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