Completed
Push — master ( 3ac846...67b859 )
by Adrien
07:43
created

InvoicerTest::testInvoice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nc 1
nop 0
dl 0
loc 13
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ApplicationTest\Service;
6
7
use Application\Model\Account;
8
use Application\Model\Bookable;
9
use Application\Model\Booking;
10
use Application\Model\TransactionLine;
11
use Application\Model\User;
12
use Application\Service\Invoicer;
13
use ApplicationTest\Traits\TestWithTransaction;
14
use PHPUnit\Framework\TestCase;
15
16
class InvoicerTest extends TestCase
17
{
18
    use TestWithTransaction;
19
20
    public function testInvoice(): void
21
    {
22
        global $container;
23
24
        /** @var Invoicer $invoicer */
25
        $invoicer = $container->get(Invoicer::class);
26
        $actual = $invoicer->invoicePeriodic();
27
        self::assertSame(2, $actual);
28
29
        _em()->flush();
30
31
        $actual2 = $invoicer->invoicePeriodic();
32
        self::assertSame(0, $actual2, 'should not invoice things that are already invoiced');
33
    }
34
35
    /**
36
     * @dataProvider providerInvoiceInitial
37
     *
38
     * @param string $initialPrice
39
     * @param string $periodicPrice
40
     * @param array $expected
41
     */
42
    public function testInvoiceInitial(string $initialPrice, string $periodicPrice, array $expected): void
43
    {
44
        $user = new User();
45
        $user->setFirstName('John');
46
        $user->setLastName('Doe');
47
48
        $bookable = new Bookable();
49
        $bookable->setName('My bookable');
50
        $bookable->setInitialPrice($initialPrice);
51
        $bookable->setPeriodicPrice($periodicPrice);
52
53
        $bookableAccount = new Account();
54
        $bookableAccount->setName('Bookable account');
55
        $bookable->setCreditAccount($bookableAccount);
56
57
        // Creation of booking will implicitly call the invoicer
58
        $booking = new Booking();
59
        $booking->setOwner($user);
60
        $booking->setBookable($bookable);
61
62
        $account = $user->getAccount();
63
64
        if ($expected === []) {
65
            self::assertNull($account);
66
        } else {
67
            $all = array_merge(
68
                $account->getCreditTransactionLines()->toArray(),
69
                $account->getDebitTransactionLines()->toArray()
70
            );
71
            $actual = [];
72
73
            /** @var TransactionLine $t */
74
            $transaction = null;
75
            foreach ($all as $t) {
76
                if (!$transaction) {
77
                    $transaction = $t->getTransaction();
78
                    self::assertNotNull($transaction, 'must belong to a transaction');
79
                } else {
80
                    self::assertSame($transaction, $t->getTransaction(), 'all lines should belong to same transaction');
81
                }
82
83
                $actual[] = [
84
                    $t->getName(),
85
                    $t->getBookable()->getName(),
86
                    $t->getDebit()->getName(),
87
                    $t->getCredit()->getName(),
88
                    $t->getBalance(),
89
                ];
90
            }
91
92
            self::assertSame($expected, $actual);
93
        }
94
    }
95
96
    public function providerInvoiceInitial(): array
97
    {
98
        return [
99
            'free booking should create nothing' => [
100
                '0',
101
                '0',
102
                [],
103
            ],
104
            'only initial' => [
105
                '10',
106
                '0',
107
                [
108
                    [
109
                        'Paiement ponctuel',
110
                        'My bookable',
111
                        'John Doe',
112
                        'Bookable account',
113
                        '10',
114
                    ],
115
                ],
116
            ],
117
            'only periodic' => [
118
                '0',
119
                '90',
120
                [
121
                    [
122
                        'Paiement annuel',
123
                        'My bookable',
124
                        'John Doe',
125
                        'Bookable account',
126
                        '90',
127
                    ],
128
                ],
129
            ],
130
            'both initial and periodic should create two lines' => [
131
                '10',
132
                '90',
133
                [
134
                    [
135
                        'Paiement ponctuel',
136
                        'My bookable',
137
                        'John Doe',
138
                        'Bookable account',
139
                        '10',
140
                    ],
141
                    [
142
                        'Paiement annuel',
143
                        'My bookable',
144
                        'John Doe',
145
                        'Bookable account',
146
                        '90',
147
                    ],
148
                ],
149
            ],
150
            'negative balance should swap accounts' => [
151
                '-10',
152
                '-90',
153
                [
154
                    [
155
                        'Paiement ponctuel',
156
                        'My bookable',
157
                        'Bookable account',
158
                        'John Doe',
159
                        '10',
160
                    ],
161
                    [
162
                        'Paiement annuel',
163
                        'My bookable',
164
                        'Bookable account',
165
                        'John Doe',
166
                        '90',
167
                    ],
168
                ],
169
            ],
170
        ];
171
    }
172
173
    public function testInvoicerNotCalled(): void
174
    {
175
        $user = new User();
176
        $bookable = new Bookable();
177
        $bookable->setInitialPrice('1');
178
        $bookable->setPeriodicPrice('1');
179
180
        $bookingWithoutOwner = new Booking();
181
        $bookingWithoutOwner->setBookable($bookable);
182
183
        $bookingWithoutBookable = new Booking();
184
        $bookingWithoutBookable->setOwner($user);
185
186
        self::assertNull($user->getAccount(), 'invoicer is only called when we have both an owner and a bookable');
187
    }
188
}
189