Failed Conditions
Push — master ( 15fc02...10b36b )
by Sylvain
09:13
created

Booking::setStatus()   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 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Model;
6
7
use Application\DBAL\Types\BookingStatusType;
8
use Application\Service\Invoicer;
9
use Application\Traits\HasInternalRemarks;
10
use Application\Traits\HasRemarks;
11
use Application\Utility;
12
use Cake\Chronos\Chronos;
13
use Doctrine\ORM\Mapping as ORM;
14
use GraphQL\Doctrine\Annotation as API;
15
use Money\Money;
16
17
/**
18
 * A booking linking a user and a bookable
19
 *
20
 * @ORM\Entity(repositoryClass="Application\Repository\BookingRepository")
21
 * @ORM\AssociationOverrides({
22
 *     @ORM\AssociationOverride(name="owner", inversedBy="bookings")
23
 * })
24
 * @API\Sorting({
25
 *     "Application\Api\Input\Sorting\Bookable"
26
 * })
27
 */
28
class Booking extends AbstractModel
29
{
30
    use HasRemarks;
31
    use HasInternalRemarks;
32
33
    /**
34
     * @var string
35
     *
36
     * @ORM\Column(type="BookingStatus", length=10, options={"default" = BookingStatusType::APPLICATION})
37
     */
38
    private $status = BookingStatusType::APPLICATION;
39
40
    /**
41
     * @var int
42
     * @ORM\Column(type="integer", options={"unsigned" = true, "default" = 1})
43
     */
44
    private $participantCount = 1;
45
46
    /**
47
     * @var string
48
     *
49
     * @ORM\Column(type="string", length=50, options={"default" = ""})
50
     */
51
    private $destination = '';
52
53
    /**
54
     * @var string
55
     *
56
     * @ORM\Column(type="text", length=65535, options={"default" = ""})
57
     */
58
    private $startComment = '';
59
60
    /**
61
     * @var string
62
     *
63
     * @ORM\Column(type="text", length=65535, options={"default" = ""})
64
     */
65
    private $endComment = '';
66
67
    /**
68
     * @var Chronos
69
     *
70
     * @ORM\Column(type="datetime")
71
     */
72
    private $startDate;
73
74
    /**
75
     * @var Chronos
76
     *
77
     * @ORM\Column(type="datetime", nullable=true)
78
     */
79
    private $endDate;
80
81
    /**
82
     * @var string
83
     *
84
     * @ORM\Column(type="string", length=50, options={"default" = ""})
85
     */
86
    private $estimatedEndDate = '';
87
88
    /**
89
     * @var null|Bookable
90
     *
91
     * @ORM\ManyToOne(targetEntity="Bookable", inversedBy="bookings")
92
     * @ORM\JoinColumns({
93
     *     @ORM\JoinColumn(onDelete="CASCADE")
94
     * })
95
     */
96
    private $bookable;
97
98
    /**
99
     * Constructor
100
     */
101 23
    public function __construct()
102
    {
103 23
    }
104
105 16
    public function setOwner(User $owner = null): void
106
    {
107 16
        if ($this->getOwner()) {
108 3
            $this->getOwner()->bookingRemoved($this);
109
        }
110
111 16
        parent::setOwner($owner);
112
113 16
        if ($this->getOwner()) {
114 14
            $this->getOwner()->bookingAdded($this);
115
        }
116
117 16
        $this->invoiceInitial();
118 16
    }
119
120
    /**
121
     * Total count of participant, at least 1.
122
     *
123
     * @return int
124
     */
125
    public function getParticipantCount(): int
126
    {
127
        return $this->participantCount;
128
    }
129
130
    /**
131
     * @param int $participantCount
132
     */
133 2
    public function setParticipantCount(int $participantCount): void
134
    {
135 2
        $this->participantCount = $participantCount;
136 2
    }
137
138
    /**
139
     * @return string
140
     */
141
    public function getDestination(): string
142
    {
143
        return $this->destination;
144
    }
145
146
    /**
147
     * @param string $destination
148
     */
149 2
    public function setDestination(string $destination): void
150
    {
151 2
        $this->destination = $destination;
152 2
    }
153
154
    /**
155
     * @return string
156
     */
157
    public function getStartComment(): string
158
    {
159
        return $this->startComment;
160
    }
161
162
    /**
163
     * @param string $startComment
164
     */
165 2
    public function setStartComment(string $startComment): void
166
    {
167 2
        $this->startComment = $startComment;
168 2
    }
169
170
    /**
171
     * @return string
172
     */
173
    public function getEndComment(): string
174
    {
175
        return $this->endComment;
176
    }
177
178
    /**
179
     * @param string $endComment
180
     */
181 2
    public function setEndComment(string $endComment): void
182
    {
183 2
        $this->endComment = $endComment;
184 2
    }
185
186
    /**
187
     * @return Chronos
188
     */
189
    public function getStartDate(): Chronos
190
    {
191
        return $this->startDate;
192
    }
193
194
    /**
195
     * @param Chronos $startDate
196
     */
197 2
    public function setStartDate(Chronos $startDate): void
198
    {
199 2
        $this->startDate = $startDate;
200 2
    }
201
202
    /**
203
     * @return null|Chronos
204
     */
205 1
    public function getEndDate(): ?Chronos
206
    {
207 1
        return $this->endDate;
208
    }
209
210
    /**
211
     * @param null|Chronos $endDate
212
     */
213 1
    public function setEndDate(?Chronos $endDate): void
214
    {
215 1
        $this->endDate = $endDate;
216 1
    }
217
218
    /**
219
     * @return string
220
     */
221
    public function getEstimatedEndDate(): string
222
    {
223
        return $this->estimatedEndDate;
224
    }
225
226
    /**
227
     * @param string $estimatedEndDate
228
     */
229 2
    public function setEstimatedEndDate(string $estimatedEndDate): void
230
    {
231 2
        $this->estimatedEndDate = $estimatedEndDate;
232 2
    }
233
234
    /**
235
     * Get bookable, may be null for "my own material" case
236
     *
237
     * @return null|Bookable
238
     */
239 40
    public function getBookable(): ?Bookable
240
    {
241 40
        return $this->bookable;
242
    }
243
244
    /**
245
     * Set bookable
246
     *
247
     * @param null|Bookable $bookable
248
     */
249 12
    public function setBookable(?Bookable $bookable): void
250
    {
251 12
        if ($this->bookable) {
252 1
            $this->bookable->bookingRemoved($this);
253
        }
254
255 12
        $this->bookable = $bookable;
256
257 12
        if ($this->bookable) {
258 12
            $this->bookable->bookingAdded($this);
259
        }
260
261 12
        $this->invoiceInitial();
262 12
    }
263
264
    /**
265
     * @API\Field(type="BookingStatus")
266
     *
267
     * @return string
268
     */
269 7
    public function getStatus(): string
270
    {
271 7
        return $this->status;
272
    }
273
274
    /**
275
     * @API\Input(type="BookingStatus")
276
     *
277
     * @param string $status
278
     */
279 8
    public function setStatus(string $status): void
280
    {
281 8
        $this->status = $status;
282 8
        $this->invoiceInitial();
283 8
    }
284
285
    /**
286
     * Mark the booking as terminated with an optional comment,
287
     * but only if not already terminated
288
     *
289
     * @param null|string $comment
290
     */
291
    public function terminate(?string $comment): void
292
    {
293
        // Booking can only be terminated once
294
        if (!$this->getEndDate()) {
295
            $this->setEndDate(Utility::getNow());
296
            if ($comment) {
297
                $this->setEndComment($comment);
298
            }
299
        }
300
    }
301
302
    /**
303
     * If the booking is complete, will make initial invoicing
304
     */
305 20
    private function invoiceInitial(): void
306
    {
307 20
        if (!$this->getOwner() || !$this->getBookable()) {
308 20
            return;
309
        }
310
311 7
        global $container;
312
313
        /** @var Invoicer $invoicer */
314 7
        $invoicer = $container->get(Invoicer::class);
315 7
        $invoicer->invoiceInitial($this->getOwner(), $this);
316 7
    }
317
318
    /**
319
     * Returns the next invoicable periodic price
320
     *
321
     * In case it uses shared admin_only bookables, the price is divided by the number of usages
322
     *
323
     * @return Money
324
     */
325 7
    public function getPeriodicPrice(): Money
326
    {
327 7
        $bookable = $this->getBookable();
328 7
        $bookings = $bookable->getSharedBookings();
329
330 7
        if (!$bookings) {
331 6
            return $bookable->getPeriodicPrice();
332
        }
333
334 1
        return $bookable->getPeriodicPrice()->divide(count($bookings));
335
    }
336
}
337