diff --git a/.gitattributes b/.gitattributes index 3b41682..44153cd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,9 @@ /mvnw text eol=lf *.cmd text eol=crlf +* text eol=lf +*.bat eol=crlf +*.htm text diff=html +*.html text diff=html +*.xhtml text diff=html +*.java text diff=java +*.css text diff=css \ No newline at end of file diff --git a/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/entity/AppointmentEntity.java b/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/entity/AppointmentEntity.java index 28e888f..12eeb0c 100644 --- a/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/entity/AppointmentEntity.java +++ b/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/entity/AppointmentEntity.java @@ -1,6 +1,7 @@ package com.capgemini.training.appointmentbooking.dataaccess.entity; import java.time.Instant; +import java.util.Objects; import com.capgemini.training.appointmentbooking.common.datatype.AppointmentStatus; @@ -38,7 +39,30 @@ public class AppointmentEntity extends BaseEntity { @Column(name = "DATE_TIME") private Instant dateTime; + @Column(name = "END_DATE_TIME") + private Instant endsAt; + @Enumerated(EnumType.STRING) private AppointmentStatus status; + @Override + public void prePersist() { + super.prePersist(); + validateDates(); + } + + @Override + public void preUpdate() { + super.preUpdate(); + validateDates(); + } + + private void validateDates() { + Objects.requireNonNull(this.dateTime); + Objects.requireNonNull(this.endsAt); + if (!this.endsAt.isAfter(this.dateTime)) { + throw new IllegalStateException( + String.format("Starting date: %s must be before end date: %s", this.dateTime, this.endsAt)); + } + } } diff --git a/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepository.java b/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepository.java index 03541a8..160db4d 100644 --- a/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepository.java +++ b/src/main/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepository.java @@ -77,10 +77,10 @@ SELECT CASE WHEN COUNT(a) > 0 THEN TRUE ELSE FALSE END FROM AppointmentEntity a JOIN a.treatment t WHERE t.specialist.id = :specialistId - AND a.dateTime = :date + AND NOT ( a.endsAt <= :startDate OR a.dateTime >= :endDate) AND a.status <> com.capgemini.training.appointmentbooking.common.datatype.AppointmentStatus.CANCELLED """) boolean hasConflictingAppointmentBySpecialistIdAndDateTime(@Param("specialistId") Long specialistId, - @Param("date") Instant date); + @Param("startDate") Instant startDate, @Param("endDate") Instant endDate); } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b4e3d67..0ac9cd9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -13,3 +13,7 @@ management.endpoints.web.exposure.include=* spring.flyway.locations=classpath:db/migration spring.flyway.enabled=true spring.flyway.clean-on-validation-error=true + +spring.jpa.hibernate.ddl-auto=none + +spring.banner.location=classpath:/banner/jbd_banner.txt diff --git a/src/main/resources/banner/jbd_banner.txt b/src/main/resources/banner/jbd_banner.txt new file mode 100644 index 0000000..f19aec5 --- /dev/null +++ b/src/main/resources/banner/jbd_banner.txt @@ -0,0 +1,9 @@ + ____. __________ __ .___ ________ .__ + | |____ ___ _______ \______ \_____ ____ | | __ ____ ____ __| _/ \______ \ _______ __ ____ | | ____ ______ ___________ + | \__ \\ \/ /\__ \ | | _/\__ \ _/ ___\| |/ // __ \ / \ / __ | | | \_/ __ \ \/ // __ \| | / _ \\____ \_/ __ \_ __ \ +/\__| |/ __ \\ / / __ \_ | | \ / __ \\ \___| <\ ___/| | \/ /_/ | | ` \ ___/\ /\ ___/| |_( <_> ) |_> > ___/| | \/ +\________(____ /\_/ (____ / |______ /(____ /\___ >__|_ \\___ >___| /\____ | /_______ /\___ >\_/ \___ >____/\____/| __/ \___ >__| + \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |__| \/ + +${application.title} ${application.version} +Powered by Spring Boot ${spring-boot.version} \ No newline at end of file diff --git a/src/main/resources/db/migration/1.0/V0001__Create_schema.sql b/src/main/resources/db/migration/1.0/V0001__Create_schema.sql index cea91c1..b3ed7d7 100644 --- a/src/main/resources/db/migration/1.0/V0001__Create_schema.sql +++ b/src/main/resources/db/migration/1.0/V0001__Create_schema.sql @@ -49,6 +49,7 @@ CREATE TABLE APPOINTMENT ( ID NUMBER(19,0) NOT NULL, VERSION INTEGER NOT NULL, DATE_TIME TIMESTAMP NOT NULL, + END_DATE_TIME TIMESTAMP NOT NULL, STATUS VARCHAR(128) NOT NULL DEFAULT 'SCHEDULED', CLIENT_ID NUMBER(19,0) NOT NULL, TREATMENT_ID NUMBER(19,0) NOT NULL, @@ -69,6 +70,6 @@ CREATE SEQUENCE APPOINTMENT_SEQ START WITH 1 INCREMENT BY 100 NOCYCLE; -- CREATING INDEX CREATE INDEX IDX_CLIENT_USER ON CLIENT(USER_ID); CREATE INDEX IDX_SPECIAL_USER ON SPECIALIST(USER_ID); -CREATE INDEX IDX_TREATM_SPECIAL ON TREATMENT(SPECIALIST_ID); +CREATE INDEX IDX_TREATM_SPECIAL ON TREATMENT(SPECIALIST_ID, ID); CREATE INDEX IDX_APPOINT_CLIENT ON APPOINTMENT(CLIENT_ID); -CREATE INDEX IDX_APPOINT_TREATM ON APPOINTMENT(TREATMENT_ID); \ No newline at end of file +CREATE INDEX IDX_APPOINT_TREATM ON APPOINTMENT(TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS); \ No newline at end of file diff --git a/src/main/resources/db/migration/1.0/V0002__Create_mockdata.sql b/src/main/resources/db/migration/1.0/V0002__Create_mockdata.sql index 24c169f..ffe8296 100644 --- a/src/main/resources/db/migration/1.0/V0002__Create_mockdata.sql +++ b/src/main/resources/db/migration/1.0/V0002__Create_mockdata.sql @@ -37,23 +37,23 @@ INSERT INTO TREATMENT(ID, VERSION, NAME, DESCRIPTION, DURATION_MINUTES, SPECIALI INSERT INTO TREATMENT(ID, VERSION, NAME, DESCRIPTION, DURATION_MINUTES, SPECIALIST_ID, CREATED, LAST_UPDATED) VALUES (-12, 0, 'Rekonstrukcja więzadła ACL', 'Rekonstrukcją więzadła krzyżowego przedniego (ACL) z zastąpieniem uszkodzonego więzadła nowym więzadłem ze ścięgien pacjenta.', 180, -4, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -- APPOINTMENTS -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-1, 0, -1, -1, '2024-03-01 09:00:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-2, 0, -2, -3, '2024-03-02 10:30:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-3, 0, -3, -5, '2024-03-03 14:00:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-4, 0, -4, -10, '2024-03-04 08:15:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-5, 0, -1, -2, '2024-03-05 11:45:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-6, 0, -2, -4, '2024-03-06 16:30:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-7, 0, -3, -6, '2024-03-07 09:30:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-8, 0, -4, -11, '2024-03-08 13:45:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-9, 0, -1, -7, '2024-03-09 10:00:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-10, 0, -2, -8, '2024-03-10 12:30:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-11, 0, -3, -9, '2024-03-11 15:00:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-12, 0, -4, -12, '2024-03-12 17:15:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-13, 0, -1, -1, '2024-03-13 08:30:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-14, 0, -2, -3, '2024-03-14 11:00:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-15, 0, -3, -5, '2024-03-15 13:00:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-16, 0, -4, -10, '2024-03-16 09:15:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-17, 0, -1, -2, '2024-03-17 14:45:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-18, 0, -2, -4, '2024-03-18 16:00:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-19, 0, -3, -6, '2024-03-19 10:45:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-20, 0, -4, -11, '2024-03-20 12:15:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); \ No newline at end of file +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-1, 0, -1, -1, '2024-03-01 09:00:00', '2024-03-01 09:15:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-2, 0, -2, -3, '2024-03-02 10:30:00', '2024-03-02 10:45:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-3, 0, -3, -5, '2024-03-03 14:00:00', '2024-03-03 14:15:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-4, 0, -4, -10, '2024-03-04 08:15:00', '2024-03-04 08:30:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-5, 0, -1, -2, '2024-03-05 11:45:00', '2024-03-05 12:00:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-6, 0, -2, -4, '2024-03-06 16:30:00', '2024-03-06 16:45:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-7, 0, -3, -6, '2024-03-07 09:30:00', '2024-03-07 09:45:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-8, 0, -4, -11, '2024-03-08 13:45:00', '2024-03-08 14:00:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-9, 0, -1, -7, '2024-03-09 10:00:00', '2024-03-09 10:15:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-10, 0, -2, -8, '2024-03-10 12:30:00', '2024-03-10 12:45:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-11, 0, -3, -9, '2024-03-11 15:00:00', '2024-03-11 15:15:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-12, 0, -4, -12,'2024-03-12 17:15:00', '2024-03-12 17:30:00','SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-13, 0, -1, -1, '2024-03-13 08:30:00', '2024-03-13 08:45:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-14, 0, -2, -3, '2024-03-14 11:00:00', '2024-03-14 11:15:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-15, 0, -3, -5, '2024-03-15 13:00:00', '2024-03-15 13:15:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-16, 0, -4, -10,'2024-03-16 09:15:00', '2024-03-16 09:30:00','SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-17, 0, -1, -2, '2024-03-17 14:45:00', '2024-03-17 15:00:00', 'COMPLETED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-18, 0, -2, -4, '2024-03-18 16:00:00', '2024-03-18 16:15:00', 'SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-19, 0, -3, -6, '2024-03-19 10:45:00', '2024-03-19 11:00:00', 'CANCELLED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO APPOINTMENT(ID, VERSION, CLIENT_ID, TREATMENT_ID, DATE_TIME, END_DATE_TIME, STATUS, CREATED, LAST_UPDATED) VALUES (-20, 0, -4, -11,'2024-03-20 12:15:00', '2024-03-20 12:30:00','SCHEDULED', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); \ No newline at end of file diff --git a/src/test/java/com/capgemini/training/appointmentbooking/common/BaseDataJpaTest.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/common/BaseDataJpaTest.java similarity index 82% rename from src/test/java/com/capgemini/training/appointmentbooking/common/BaseDataJpaTest.java rename to src/test/java/com/capgemini/training/appointmentbooking/dataaccess/common/BaseDataJpaTest.java index aebe70e..a9b3784 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/common/BaseDataJpaTest.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/common/BaseDataJpaTest.java @@ -1,4 +1,4 @@ -package com.capgemini.training.appointmentbooking.common; +package com.capgemini.training.appointmentbooking.dataaccess.common; import com.capgemini.training.appointmentbooking.dataaccess.config.DataaccessConfiguration; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; diff --git a/src/test/java/com/capgemini/training/appointmentbooking/common/BaseTest.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/common/BaseTest.java similarity index 86% rename from src/test/java/com/capgemini/training/appointmentbooking/common/BaseTest.java rename to src/test/java/com/capgemini/training/appointmentbooking/dataaccess/common/BaseTest.java index a6a0e2a..92b49ec 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/common/BaseTest.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/common/BaseTest.java @@ -1,4 +1,4 @@ -package com.capgemini.training.appointmentbooking.common; +package com.capgemini.training.appointmentbooking.dataaccess.common; import org.assertj.core.api.WithAssertions; diff --git a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/entity/EntitySmokeIT.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/entity/EntitySmokeIT.java index bfccc64..fb69d52 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/entity/EntitySmokeIT.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/entity/EntitySmokeIT.java @@ -15,7 +15,7 @@ // Use LAZY bootstrap mode to avoid initializing all Spring Data JPA repositories during test startup. // This improves performance and reduces test context size, since we only use EntityManager in this test. @DataJpaTest(bootstrapMode = BootstrapMode.LAZY) -public class EntitySmokeIT { +class EntitySmokeIT { @PersistenceContext private EntityManager em; diff --git a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepositoryIT.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepositoryIT.java index eaf926a..7154dfb 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepositoryIT.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/AppointmentRepositoryIT.java @@ -1,6 +1,6 @@ package com.capgemini.training.appointmentbooking.dataaccess.repository; -import com.capgemini.training.appointmentbooking.common.BaseDataJpaTest; +import com.capgemini.training.appointmentbooking.dataaccess.common.BaseDataJpaTest; import com.capgemini.training.appointmentbooking.common.datatype.AppointmentStatus; import com.capgemini.training.appointmentbooking.dataaccess.entity.AppointmentEntity; import com.capgemini.training.appointmentbooking.dataaccess.entity.ClientEntity; @@ -14,7 +14,7 @@ import java.util.List; import java.util.Optional; -public class AppointmentRepositoryIT extends BaseDataJpaTest { +class AppointmentRepositoryIT extends BaseDataJpaTest { @Inject private AppointmentRepository appointmentRepository; @@ -161,16 +161,82 @@ void shouldFindAppointmentsBySpecialistIdBeforeDate() { .allMatch(a -> a.getDateTime().isBefore(date), "All appointments should be before the given date"); } + /** + * Given a saved appointment from 11:45 to 12:00, this test ensures that an + * earlier appointment does not trigger a conflict. + */ @Test - void shouldFindConflictedAppointment() { - // given + void shouldNotFindConflictingAppointmentWhenNewAppointmentEndsBeforeExisting() { Long specialistId = -1L; - Instant date = toInstant("2024-03-05 11:45:00"); + Instant startDate = toInstant("2024-03-05 11:30:00"); + Instant endDate = toInstant("2024-03-05 11:45:00"); - // when - boolean conflict = appointmentRepository.hasConflictingAppointmentBySpecialistIdAndDateTime(specialistId, date); + boolean conflict = appointmentRepository.hasConflictingAppointmentBySpecialistIdAndDateTime(specialistId, + startDate, endDate); + + assertThat(conflict).isFalse(); + } + + /** + * Ensures that an appointment starting after an existing one does not conflict. + */ + @Test + void shouldNotFindConflictingAppointmentWhenNewAppointmentStartsAfterExisting() { + Long specialistId = -1L; + Instant startDate = toInstant("2024-03-05 12:00:00"); + Instant endDate = toInstant("2024-03-05 12:01:00"); + + boolean conflict = appointmentRepository.hasConflictingAppointmentBySpecialistIdAndDateTime(specialistId, + startDate, endDate); + + assertThat(conflict).isFalse(); + } + + /** + * Verifies that an appointment starting and ending at exactly the same time as + * an existing one is treated as a conflict. + */ + @Test + void shouldFindConflictingAppointmentWhenTimeMatchesExactly() { + Long specialistId = -1L; + Instant startDate = toInstant("2024-03-05 11:45:00"); + Instant endDate = toInstant("2024-03-05 12:00:00"); + + boolean conflict = appointmentRepository.hasConflictingAppointmentBySpecialistIdAndDateTime(specialistId, + startDate, endDate); + + assertThat(conflict).isTrue(); + } + + /** + * Ensures that an appointment which starts before and ends during the existing + * one is considered a conflict. + */ + @Test + void shouldFindConflictingAppointmentWhenEndingOverlapsWithExisting() { + Long specialistId = -1L; + Instant startDate = toInstant("2024-03-05 11:40:00"); + Instant endDate = toInstant("2024-03-05 11:45:01"); + + boolean conflict = appointmentRepository.hasConflictingAppointmentBySpecialistIdAndDateTime(specialistId, + startDate, endDate); + + assertThat(conflict).isTrue(); + } + + /** + * Checks that an appointment starting just before the end of an existing one is + * correctly flagged as a conflict. + */ + @Test + void shouldFindConflictingAppointmentWhenStartingBeforeExistingEnds() { + Long specialistId = -1L; + Instant startDate = toInstant("2024-03-05 11:59:59"); + Instant endDate = toInstant("2024-03-05 12:05:00"); + + boolean conflict = appointmentRepository.hasConflictingAppointmentBySpecialistIdAndDateTime(specialistId, + startDate, endDate); - // then assertThat(conflict).isTrue(); } } diff --git a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/ClientRepositoryIT.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/ClientRepositoryIT.java index 2340b77..005f52a 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/ClientRepositoryIT.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/ClientRepositoryIT.java @@ -1,13 +1,13 @@ package com.capgemini.training.appointmentbooking.dataaccess.repository; -import com.capgemini.training.appointmentbooking.common.BaseDataJpaTest; +import com.capgemini.training.appointmentbooking.dataaccess.common.BaseDataJpaTest; import com.capgemini.training.appointmentbooking.dataaccess.entity.ClientEntity; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; import java.util.List; -public class ClientRepositoryIT extends BaseDataJpaTest { +class ClientRepositoryIT extends BaseDataJpaTest { @Inject private ClientRepository clientRepository; diff --git a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/SpecialistRepositoryIT.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/SpecialistRepositoryIT.java index 7b88e04..a21debf 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/SpecialistRepositoryIT.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/SpecialistRepositoryIT.java @@ -1,6 +1,6 @@ package com.capgemini.training.appointmentbooking.dataaccess.repository; -import com.capgemini.training.appointmentbooking.common.BaseDataJpaTest; +import com.capgemini.training.appointmentbooking.dataaccess.common.BaseDataJpaTest; import com.capgemini.training.appointmentbooking.common.datatype.Specialization; import com.capgemini.training.appointmentbooking.dataaccess.entity.SpecialistEntity; import jakarta.inject.Inject; @@ -8,7 +8,7 @@ import java.util.List; -public class SpecialistRepositoryIT extends BaseDataJpaTest { +class SpecialistRepositoryIT extends BaseDataJpaTest { @Inject private SpecialistRepository specialistRepository; diff --git a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/TreatmentRepositoryIT.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/TreatmentRepositoryIT.java index 9d4f7bb..78598af 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/TreatmentRepositoryIT.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/TreatmentRepositoryIT.java @@ -1,6 +1,6 @@ package com.capgemini.training.appointmentbooking.dataaccess.repository; -import com.capgemini.training.appointmentbooking.common.BaseDataJpaTest; +import com.capgemini.training.appointmentbooking.dataaccess.common.BaseDataJpaTest; import com.capgemini.training.appointmentbooking.common.datatype.Specialization; import com.capgemini.training.appointmentbooking.dataaccess.entity.SpecialistEntity; import com.capgemini.training.appointmentbooking.dataaccess.entity.TreatmentEntity; @@ -11,7 +11,7 @@ import java.util.List; import java.util.Optional; -public class TreatmentRepositoryIT extends BaseDataJpaTest { +class TreatmentRepositoryIT extends BaseDataJpaTest { @Inject private TreatmentRepository treatmentRepository; diff --git a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/UserRepositoryIT.java b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/UserRepositoryIT.java index 3edbdb1..877f88d 100644 --- a/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/UserRepositoryIT.java +++ b/src/test/java/com/capgemini/training/appointmentbooking/dataaccess/repository/UserRepositoryIT.java @@ -1,6 +1,6 @@ package com.capgemini.training.appointmentbooking.dataaccess.repository; -import com.capgemini.training.appointmentbooking.common.BaseDataJpaTest; +import com.capgemini.training.appointmentbooking.dataaccess.common.BaseDataJpaTest; import com.capgemini.training.appointmentbooking.dataaccess.entity.UserEntity; import com.capgemini.training.appointmentbooking.dataaccess.repository.criteria.UserCriteria; import jakarta.inject.Inject; @@ -8,7 +8,7 @@ import java.util.List; -public class UserRepositoryIT extends BaseDataJpaTest { +class UserRepositoryIT extends BaseDataJpaTest { @Inject private UserRepository userRepository;