Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
Loan
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
10 / 10
12
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBookId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBorrowedAt
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDueAt
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getReturnedAt
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStatus
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isOverdue
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 markAsReturned
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10namespace AppDemo\Loan\Domain;
11
12use AppDemo\Loan\Domain\Exception\LoanAlreadyReturnedException;
13use DateTimeImmutable;
14use Phexium\Domain\EntityAbstract;
15use Phexium\Domain\EntityInterface;
16use Phexium\Domain\Id\IdInterface;
17
18class Loan extends EntityAbstract implements EntityInterface
19{
20    public function __construct(
21        private readonly IdInterface $id,
22        private readonly IdInterface $userId,
23        private readonly IdInterface $bookId,
24        private readonly DateTimeImmutable $borrowedAt,
25        private readonly DateTimeImmutable $dueAt,
26        private ?DateTimeImmutable $returnedAt,
27        private LoanStatus $status
28    ) {}
29
30    public function getId(): IdInterface
31    {
32        return $this->id;
33    }
34
35    public function getUserId(): IdInterface
36    {
37        return $this->userId;
38    }
39
40    public function getBookId(): IdInterface
41    {
42        return $this->bookId;
43    }
44
45    public function getBorrowedAt(): DateTimeImmutable
46    {
47        return $this->borrowedAt;
48    }
49
50    public function getDueAt(): DateTimeImmutable
51    {
52        return $this->dueAt;
53    }
54
55    public function getReturnedAt(): ?DateTimeImmutable
56    {
57        return $this->returnedAt;
58    }
59
60    public function getStatus(): LoanStatus
61    {
62        return $this->status;
63    }
64
65    public function isOverdue(DateTimeImmutable $now): bool
66    {
67        if ($this->returnedAt instanceof DateTimeImmutable) {
68            return false;
69        }
70
71        return $this->dueAt < $now;
72    }
73
74    public function markAsReturned(DateTimeImmutable $returnedAt): void
75    {
76        if (!$this->status->canBeReturned()) {
77            throw LoanAlreadyReturnedException::forLoan($this->id);
78        }
79
80        $this->status = LoanStatus::Returned;
81        $this->returnedAt = $returnedAt;
82    }
83}