Completed
Push — master ( dc6e13...340cc5 )
by Adrien
07:39
created

Invoicer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Service;
6
7
use Application\Model\Account;
8
use Application\Model\Booking;
9
use Application\Model\Transaction;
10
use Application\Model\TransactionLine;
11
use Application\Model\User;
12
use Cake\Chronos\Date;
13
use Doctrine\ORM\EntityManager;
14
15
class Invoicer
16
{
17
    /**
18
     * @var EntityManager
19
     */
20
    private $entityManager;
21
22
    /**
23
     * @var Mailer
24
     */
25
    private $mailer;
26
27
    /**
28
     * @var int
29
     */
30
    private $count = 0;
31
32
    /**
33
     * @var bool
34
     */
35
    private $sendEmailNow = false;
36
37 1
    public function __construct(EntityManager $entityManager, Mailer $mailer)
38
    {
39 1
        $this->entityManager = $entityManager;
40 1
        $this->mailer = $mailer;
41 1
    }
42
43 2
    public function invoice(?User $user = null): int
44
    {
45 2
        $this->sendEmailNow = (bool) $user;
46 2
        $this->count = 0;
47 2
        $bookings = $this->entityManager->getRepository(Booking::class)->getAllToInvoice($user);
48
49 2
        $user = null;
50 2
        $bookingPerUser = [];
51
52
        /** @var Booking $booking */
53 2
        foreach ($bookings as $booking) {
54 2
            if ($user !== $booking->getOwner()) {
55 2
                $this->invoiceOne($user, $bookingPerUser);
56
57 2
                $user = $booking->getOwner();
58 2
                $bookingPerUser = [];
59
            }
60
61 2
            $bookingPerUser[] = $booking;
62
        }
63 2
        $this->invoiceOne($user, $bookingPerUser);
64
65 2
        return $this->count;
66
    }
67
68
    /**
69
     * @param User $user
70
     * @param Booking[] $bookings
71
     *
72
     * @return Transaction
73
     */
74 2
    private function createTransaction(User $user, array $bookings): Transaction
75
    {
76 2
        $account = $this->entityManager->getRepository(Account::class)->getOrCreate($user);
77 2
        $transaction = new Transaction();
78 2
        $transaction->setTransactionDate(Date::today());
79 2
        $transaction->setName('Cotisation et services ' . Date::today()->format('Y'));
80 2
        $this->entityManager->persist($transaction);
81
82 2
        foreach ($bookings as $booking) {
83 2
            $bookable = $booking->getBookable();
84 2
            $transactionLine = new TransactionLine();
85 2
            $this->entityManager->persist($transactionLine);
86
87 2
            $transactionLine->setName('Paiement depuis crédit MyIchtus');
88 2
            $transactionLine->setBookable($bookable);
89 2
            $transactionLine->setDebit($account);
90 2
            $transactionLine->setCredit($bookable->getCreditAccount());
91 2
            $transactionLine->setBalance($this->calculateBalance($booking));
92 2
            $transactionLine->setTransaction($transaction);
93 2
            $transactionLine->setTransactionDate(Date::today());
94
        }
95
96 2
        return $transaction;
97
    }
98
99
    /**
100
     * @param Booking $booking
101
     *
102
     * @return string
103
     */
104 2
    private function calculateBalance(Booking $booking): string
105
    {
106 2
        $bookable = $booking->getBookable();
107 2
        $simultaneous = $bookable->getSimultaneousBookingMaximum();
108
109
        // If infinite booking, pay full price
110 2
        if (!($simultaneous > 1)) {
111 2
            $simultaneous = 1;
112
        }
113
114 2
        $price = (string) ($bookable->getPeriodicPrice() / $simultaneous);
115
116 2
        return $price;
117
    }
118
119
    /**
120
     * @param null|User $user
121
     * @param Booking[] $bookings
122
     */
123 2
    private function invoiceOne(?User $user, array $bookings): void
124
    {
125 2
        if (!$user || !$bookings) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $bookings of type Application\Model\Booking[] 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...
126 2
            return;
127
        }
128
129 2
        $transaction = $this->createTransaction($user, $bookings);
130 2
        $this->entityManager->flush();
131 2
        $this->entityManager->refresh($user->getAccount());
132
133 2
        if ($user->getEmail()) {
134 2
            $message = $this->mailer->queueInvoice($user, $transaction);
135 2
            $this->entityManager->flush();
136
137 2
            if ($this->sendEmailNow) {
138 2
                $this->mailer->sendMessageAsync($message);
139
            }
140
        } else {
141
            _log()->err('Cannot notify invoice for user without email', ['user' => $user->getId(), 'transaction' => $transaction->getId()]);
142
        }
143
144 2
        ++$this->count;
145 2
    }
146
}
147