Passed
Push — master ( b3e1ed...202dba )
by Adrien
07:28
created

Invoicer::createTransaction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 17
nc 2
nop 2
dl 0
loc 23
rs 9.7
c 0
b 0
f 0
ccs 18
cts 18
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\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 1
    public function __construct(EntityManager $entityManager, Mailer $mailer)
33
    {
34 1
        $this->entityManager = $entityManager;
35 1
        $this->mailer = $mailer;
36 1
    }
37
38 1
    public function invoice(): int
39
    {
40 1
        $this->count = 0;
41 1
        $bookings = $this->entityManager->getRepository(Booking::class)->getAllToInvoice();
42
43 1
        $user = null;
44 1
        $bookingPerUser = [];
45
46
        /** @var Booking $booking */
47 1
        foreach ($bookings as $booking) {
48 1
            if ($user !== $booking->getOwner()) {
49 1
                $this->invoiceOne($user, $bookingPerUser);
50
51 1
                $user = $booking->getOwner();
52 1
                $bookingPerUser = [];
53
            }
54
55 1
            $bookingPerUser[] = $booking;
56
        }
57 1
        $this->invoiceOne($user, $bookingPerUser);
58
59 1
        return $this->count;
60
    }
61
62
    /**
63
     * @param User $user
64
     * @param Booking[] $bookings
65
     *
66
     * @return Transaction
67
     */
68 1
    private function createTransaction(User $user, array $bookings): Transaction
69
    {
70 1
        $account = $this->entityManager->getRepository(Account::class)->getOrCreate($user);
71 1
        $transaction = new Transaction();
72 1
        $transaction->setTransactionDate(Date::today());
73 1
        $transaction->setName('Cotisation et services ' . Date::today()->format('Y'));
74 1
        $this->entityManager->persist($transaction);
75
76 1
        foreach ($bookings as $booking) {
77 1
            $bookable = $booking->getBookable();
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($booking));
86 1
            $transactionLine->setTransaction($transaction);
87 1
            $transactionLine->setTransactionDate(Date::today());
88
        }
89
90 1
        return $transaction;
91
    }
92
93
    /**
94
     * @param Booking $booking
95
     *
96
     * @return string
97
     */
98 1
    private function calculateBalance(Booking $booking): string
99
    {
100 1
        $bookable = $booking->getBookable();
101 1
        $simultaneous = $bookable->getSimultaneousBookingMaximum();
102
103
        // If infinite booking, pay full price
104 1
        if (!($simultaneous > 1)) {
105 1
            $simultaneous = 1;
106
        }
107
108 1
        $price = (string) ($bookable->getPeriodicPrice() / $simultaneous);
109
110 1
        return $price;
111
    }
112
113
    /**
114
     * @param null|User $user
115
     * @param Booking[] $bookings
116
     */
117 1
    private function invoiceOne(?User $user, array $bookings): void
118
    {
119 1
        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...
120 1
            return;
121
        }
122
123 1
        $transaction = $this->createTransaction($user, $bookings);
124 1
        $this->entityManager->flush();
125 1
        $this->entityManager->refresh($user->getAccount());
126
127 1
        if ($user->getEmail()) {
128 1
            $this->mailer->queueInvoice($user, $transaction);
129 1
            $this->entityManager->flush();
130
        } else {
131
            _log()->err('Cannot notify invoice for user without email', ['user' => $user->getId(), 'transaction' => $transaction->getId()]);
132
        }
133
134 1
        ++$this->count;
135 1
    }
136
}
137