Completed
Push — master ( 2197c6...b3e1ed )
by Adrien
07:42
created

Invoicer::calculateBalance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 12
rs 10
c 0
b 0
f 0
ccs 6
cts 6
cp 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Service;
6
7
use Application\Model\Account;
8
use Application\Model\Bookable;
9
use Application\Model\Booking;
10
use Application\Model\Transaction;
11
use Application\Model\TransactionLine;
12
use Application\Model\User;
13
use Cake\Chronos\Date;
14
use Doctrine\ORM\EntityManager;
15
16
class Invoicer
17
{
18
    /**
19
     * @var EntityManager
20
     */
21
    private $entityManager;
22
23
    /**
24
     * @var Mailer
25
     */
26
    private $mailer;
27
28
    /**
29
     * @var int
30
     */
31
    private $count = 0;
32
33 1
    public function __construct(EntityManager $entityManager, Mailer $mailer)
34
    {
35 1
        $this->entityManager = $entityManager;
36 1
        $this->mailer = $mailer;
37 1
    }
38
39 1
    public function invoice(): int
40
    {
41 1
        $this->count = 0;
42 1
        $bookings = $this->entityManager->getRepository(Booking::class)->getAllToInvoice();
43
44 1
        $user = null;
45 1
        $bookables = [];
46
47
        /** @var Booking $booking */
48 1
        foreach ($bookings as $booking) {
49 1
            if ($user !== $booking->getOwner()) {
50 1
                $this->invoiceOne($user, $bookables);
51
52 1
                $user = $booking->getOwner();
53 1
                $bookables = [];
54
            }
55
56 1
            $bookables[] = $booking->getBookable();
57
        }
58 1
        $this->invoiceOne($user, $bookables);
59
60 1
        return $this->count;
61
    }
62
63
    /**
64
     * @param User $user
65
     * @param Bookable[] $bookables
66
     *
67
     * @return Transaction
68
     */
69 1
    private function createTransaction(User $user, array $bookables): Transaction
70
    {
71 1
        $account = $this->entityManager->getRepository(Account::class)->getOrCreate($user);
72 1
        $transaction = new Transaction();
73 1
        $transaction->setTransactionDate(Date::today());
74 1
        $transaction->setName('Cotisation et services ' . Date::today()->format('Y'));
75 1
        $this->entityManager->persist($transaction);
76
77 1
        foreach ($bookables as $bookable) {
78 1
            $transactionLine = new TransactionLine();
79 1
            $this->entityManager->persist($transactionLine);
80
81 1
            $transactionLine->setName('Paiement depuis crédit MyIchtus');
82 1
            $transactionLine->setBookable($bookable);
83 1
            $transactionLine->setDebit($account);
84 1
            $transactionLine->setCredit($bookable->getCreditAccount());
85 1
            $transactionLine->setBalance($this->calculateBalance($bookable));
86 1
            $transactionLine->setTransaction($transaction);
87 1
            $transactionLine->setTransactionDate(Date::today());
88
        }
89
90 1
        return $transaction;
91
    }
92
93
    /**
94
     * @param Bookable $bookable
95
     *
96
     * @return string
97
     */
98 1
    private function calculateBalance(Bookable $bookable): string
99
    {
100 1
        $simultaneous = $bookable->getSimultaneousBookingMaximum();
101
102
        // If infinite booking, pay full price
103 1
        if (!($simultaneous > 1)) {
104 1
            $simultaneous = 1;
105
        }
106
107 1
        $price = (string) ($bookable->getPeriodicPrice() / $simultaneous);
108
109 1
        return $price;
110
    }
111
112
    /**
113
     * @param null|User $user
114
     * @param Bookable[] $bookables
115
     */
116 1
    private function invoiceOne(?User $user, array $bookables): void
117
    {
118 1
        if (!$user || !$bookables) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $bookables of type Application\Model\Bookable[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
119 1
            return;
120
        }
121
122 1
        $transaction = $this->createTransaction($user, $bookables);
123 1
        $this->entityManager->flush();
124 1
        $this->entityManager->refresh($user->getAccount());
125
126 1
        if ($user->getEmail()) {
127 1
            $this->mailer->queueInvoice($user, $transaction);
128 1
            $this->entityManager->flush();
129
        } else {
130
            _log()->err('Cannot notify invoice for user without email', ['user' => $user->getId(), 'transaction' => $transaction->getId()]);
131
        }
132
133 1
        ++$this->count;
134 1
    }
135
}
136