1 package io.extact.rms.application.domain;
2
3 import static java.time.temporal.ChronoUnit.*;
4 import static jakarta.persistence.AccessType.*;
5
6 import java.time.LocalDateTime;
7 import java.time.chrono.ChronoLocalDateTime;
8 import java.util.Objects;
9
10 import jakarta.persistence.Access;
11 import jakarta.persistence.Column;
12 import jakarta.persistence.Entity;
13 import jakarta.persistence.GeneratedValue;
14 import jakarta.persistence.GenerationType;
15 import jakarta.persistence.Id;
16
17 import org.apache.commons.lang3.Range;
18 import org.apache.commons.lang3.builder.ToStringBuilder;
19 import org.apache.commons.lang3.builder.ToStringStyle;
20
21 import lombok.Getter;
22 import lombok.Setter;
23
24 import io.extact.rms.application.domain.constraint.BeforeAfterDateTime;
25 import io.extact.rms.application.domain.constraint.Note;
26 import io.extact.rms.application.domain.constraint.ReserveEndDateTime;
27 import io.extact.rms.application.domain.constraint.ReserveStartDateTime;
28 import io.extact.rms.application.domain.constraint.ReserveStartDateTimeFuture;
29 import io.extact.rms.application.domain.constraint.RmsId;
30 import io.extact.rms.application.domain.constraint.BeforeAfterDateTime.BeforeAfterDateTimeValidatable;
31 import io.extact.rms.application.domain.constraint.ValidationGroups.Add;
32 import io.extact.rms.application.domain.constraint.ValidationGroups.Update;
33
34 @Access(FIELD)
35 @Entity
36 @BeforeAfterDateTime(from = "利用開始日時", to = "利用終了日時")
37 @Getter
38 @Setter
39 public class Reservation implements BeforeAfterDateTimeValidatable, Transformable, IdAccessable {
40
41
42 @Id
43 @GeneratedValue(strategy = GenerationType.IDENTITY)
44 @RmsId(groups = Update.class)
45 private Integer id;
46
47
48 @ReserveStartDateTime
49 @ReserveStartDateTimeFuture(groups = Add.class)
50 @Column(columnDefinition = "TIMESTAMP")
51 private LocalDateTime startDateTime;
52
53
54 @ReserveEndDateTime
55 @Column(columnDefinition = "TIMESTAMP")
56 private LocalDateTime endDateTime;
57
58
59 @Note
60 private String note;
61
62
63 @RmsId
64 private int rentalItemId;
65
66
67 @RmsId
68 private int userAccountId;
69
70
71 private transient UserAccount userAccount;
72
73
74 private transient RentalItem rentalItem;
75
76
77
78
79 public static Reservation of(Integer reservationId, LocalDateTime startDateTime, LocalDateTime endDateTime, String note,
80 int rentalItemId, int userAccountId) {
81
82 var entity = new Reservation();
83 entity.id = reservationId;
84 entity.startDateTime = startDateTime;
85 entity.endDateTime = endDateTime;
86 entity.note = note;
87 entity.rentalItemId = rentalItemId;
88 entity.userAccountId = userAccountId;
89 return entity;
90 }
91
92 public static Reservation ofTransient(LocalDateTime startDateTime, LocalDateTime endDateTime, String note, int rentalItemId, int userAccountId) {
93 return of(null, startDateTime, endDateTime, note, rentalItemId, userAccountId);
94 }
95
96
97
98 public void setStartDateTime(LocalDateTime startDateTime) {
99 this.startDateTime = Objects.requireNonNull(startDateTime).truncatedTo(MINUTES);
100 }
101
102 public void setEndDateTime(LocalDateTime endDateTime) {
103 this.endDateTime = Objects.requireNonNull(endDateTime).truncatedTo(MINUTES);
104 }
105
106
107
108
109 public DateTimePeriod getReservePeriod() {
110 return new DateTimePeriod(startDateTime, endDateTime);
111 }
112
113
114
115
116 @Override
117 public String toString() {
118 return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
119 }
120
121
122
123
124 public static class DateTimePeriod {
125
126 private LocalDateTime startDateTime;
127 private LocalDateTime endDateTime;
128 private Range<ChronoLocalDateTime<?>> period;
129
130 public DateTimePeriod(LocalDateTime startDateTime, LocalDateTime endDateTime) {
131 this.startDateTime = startDateTime;
132 this.endDateTime = endDateTime;
133 period = Range.between(startDateTime, endDateTime); }
134
135 public LocalDateTime getStartDateTime() {
136 return this.startDateTime;
137 }
138
139 public LocalDateTime getEndDateTime() {
140 return this.endDateTime;
141 }
142
143 public boolean isOverlappedBy(DateTimePeriod otherPeriod) {
144 return this.period.isOverlappedBy(otherPeriod.period);
145 }
146 }
147 }