Skip to content
This repository was archived by the owner on Nov 23, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
846 changes: 846 additions & 0 deletions appointment-service/APPOINTMENT_SERVICE_DOCUMENTATION.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class BusinessHours {
@GeneratedValue(strategy = GenerationType.UUID)
private String id;

@Enumerated(EnumType.STRING)
@Enumerated(EnumType.ORDINAL)
@Column(nullable = false)
private DayOfWeek dayOfWeek;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.techtorque.appointment_service.config;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

import javax.sql.DataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;

@TestConfiguration
@EnableJpaAuditing
public class TestDataSourceConfig {

@Bean
@Primary
public DataSource testDataSource() {
return DataSourceBuilder
.create()
.driverClassName("org.h2.Driver")
.url("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;DEFAULT_NULL_ORDERING=HIGH")
.username("sa")
.password("")
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.techtorque.appointment_service.config;

import org.hibernate.dialect.H2Dialect;

/**
* Custom H2 dialect for tests that handles PostgreSQL-specific types
*/
public class TestH2Dialect extends H2Dialect {

public TestH2Dialect() {
super();
}

@Override
protected void initDefaultProperties() {
super.initDefaultProperties();
// Set properties for better PostgreSQL compatibility
getDefaultProperties().setProperty("hibernate.globally_quoted_identifiers", "false");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.techtorque.appointment_service.config;

import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@TestConfiguration
@EnableJpaAuditing
@EntityScan("com.techtorque.appointment_service.entity")
@EnableJpaRepositories("com.techtorque.appointment_service.repository")
public class TestJpaConfig {
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package com.techtorque.appointment_service.repository;

import com.techtorque.appointment_service.entity.Appointment;
import com.techtorque.appointment_service.entity.AppointmentStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;

import com.techtorque.appointment_service.config.TestDataSourceConfig;
import org.springframework.context.annotation.Import;

@SpringBootTest
@ActiveProfiles("test")
@Transactional
@Import(TestDataSourceConfig.class)
class AppointmentRepositoryTest {

@Autowired
private AppointmentRepository appointmentRepository;

private Appointment testAppointment;
private LocalDateTime testDateTime;

@BeforeEach
void setUp() {
appointmentRepository.deleteAll();

testDateTime = LocalDateTime.now().plusDays(1);

Set<String> employeeIds = new HashSet<>();
employeeIds.add("emp-123");
employeeIds.add("emp-456");

testAppointment = Appointment.builder()
.customerId("customer-123")
.vehicleId("vehicle-456")
.assignedEmployeeIds(employeeIds)
.assignedBayId("bay-001")
.confirmationNumber("APT-2025-001")
.serviceType("Oil Change")
.requestedDateTime(testDateTime)
.status(AppointmentStatus.PENDING)
.specialInstructions("Please check brakes")
.build();

appointmentRepository.save(testAppointment);
}

@Test
void testFindByCustomerIdOrderByRequestedDateTimeDesc() {
// Create another appointment for the same customer
Appointment appointment2 = Appointment.builder()
.customerId("customer-123")
.vehicleId("vehicle-789")
.serviceType("Tire Rotation")
.requestedDateTime(testDateTime.plusDays(1))
.status(AppointmentStatus.CONFIRMED)
.build();
appointmentRepository.save(appointment2);

List<Appointment> appointments = appointmentRepository
.findByCustomerIdOrderByRequestedDateTimeDesc("customer-123");

assertThat(appointments).hasSize(2);
assertThat(appointments.get(0).getRequestedDateTime())
.isAfter(appointments.get(1).getRequestedDateTime());
}

@Test
void testFindByAssignedEmployeeIdAndRequestedDateTimeBetween() {
LocalDateTime start = testDateTime.minusHours(1);
LocalDateTime end = testDateTime.plusHours(1);

List<Appointment> appointments = appointmentRepository
.findByAssignedEmployeeIdAndRequestedDateTimeBetween("emp-123", start, end);

assertThat(appointments).hasSize(1);
assertThat(appointments.get(0).getId()).isEqualTo(testAppointment.getId());
}

@Test
void testFindByRequestedDateTimeBetween() {
LocalDateTime start = testDateTime.minusHours(1);
LocalDateTime end = testDateTime.plusHours(1);

List<Appointment> appointments = appointmentRepository
.findByRequestedDateTimeBetween(start, end);

assertThat(appointments).hasSize(1);
assertThat(appointments.get(0).getId()).isEqualTo(testAppointment.getId());
}

@Test
void testFindByIdAndCustomerId() {
Optional<Appointment> found = appointmentRepository
.findByIdAndCustomerId(testAppointment.getId(), "customer-123");

assertThat(found).isPresent();
assertThat(found.get().getId()).isEqualTo(testAppointment.getId());
}

@Test
void testFindByIdAndCustomerId_WrongCustomer() {
Optional<Appointment> found = appointmentRepository
.findByIdAndCustomerId(testAppointment.getId(), "wrong-customer");

assertThat(found).isEmpty();
}

@Test
void testFindWithFilters_AllFilters() {
List<Appointment> appointments = appointmentRepository.findWithFilters(
"customer-123",
"vehicle-456",
"PENDING",
testDateTime.minusHours(1),
testDateTime.plusHours(1));

assertThat(appointments).hasSize(1);
assertThat(appointments.get(0).getCustomerId()).isEqualTo("customer-123");
}

@Test
void testFindWithFilters_NullFilters() {
List<Appointment> appointments = appointmentRepository.findWithFilters(
null, null, null, null, null);

assertThat(appointments).hasSize(1);
}

@Test
void testCountByStatus() {
// Create appointments with different statuses
Appointment confirmedAppt = Appointment.builder()
.customerId("customer-456")
.vehicleId("vehicle-789")
.serviceType("Inspection")
.requestedDateTime(testDateTime.plusDays(2))
.status(AppointmentStatus.CONFIRMED)
.build();
appointmentRepository.save(confirmedAppt);

long pendingCount = appointmentRepository.countByStatus(AppointmentStatus.PENDING);
long confirmedCount = appointmentRepository.countByStatus(AppointmentStatus.CONFIRMED);

assertThat(pendingCount).isEqualTo(1);
assertThat(confirmedCount).isEqualTo(1);
}

@Test
void testFindByAssignedBayIdAndRequestedDateTimeBetweenAndStatusNot() {
LocalDateTime start = testDateTime.minusHours(1);
LocalDateTime end = testDateTime.plusHours(1);

List<Appointment> appointments = appointmentRepository
.findByAssignedBayIdAndRequestedDateTimeBetweenAndStatusNot(
"bay-001", start, end, AppointmentStatus.CANCELLED);

assertThat(appointments).hasSize(1);
assertThat(appointments.get(0).getAssignedBayId()).isEqualTo("bay-001");
}

@Test
void testFindMaxConfirmationNumberByPrefix() {
// Create appointments with sequential confirmation numbers
Appointment appt2 = Appointment.builder()
.customerId("customer-789")
.vehicleId("vehicle-101")
.confirmationNumber("APT-2025-002")
.serviceType("Brake Service")
.requestedDateTime(testDateTime.plusDays(3))
.status(AppointmentStatus.PENDING)
.build();
appointmentRepository.save(appt2);

Optional<String> maxNumber = appointmentRepository
.findMaxConfirmationNumberByPrefix("APT-2025-");

assertThat(maxNumber).isPresent();
assertThat(maxNumber.get()).isEqualTo("APT-2025-002");
}

@Test
void testSaveAndRetrieve() {
Appointment newAppointment = Appointment.builder()
.customerId("customer-new")
.vehicleId("vehicle-new")
.serviceType("Full Service")
.requestedDateTime(testDateTime.plusDays(5))
.status(AppointmentStatus.PENDING)
.build();

Appointment saved = appointmentRepository.save(newAppointment);

assertThat(saved.getId()).isNotNull();
assertThat(saved.getCustomerId()).isEqualTo("customer-new");
assertThat(saved.getServiceType()).isEqualTo("Full Service");
assertThat(saved.getStatus()).isEqualTo(AppointmentStatus.PENDING);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.techtorque.appointment_service.repository;

import com.techtorque.appointment_service.entity.BusinessHours;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;

import java.time.DayOfWeek;
import java.time.LocalTime;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;

import com.techtorque.appointment_service.config.TestDataSourceConfig;
import org.springframework.context.annotation.Import;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

@SpringBootTest
@ActiveProfiles("test")
@Transactional
@Import(TestDataSourceConfig.class)
class BusinessHoursRepositoryTest {

@Autowired
private BusinessHoursRepository businessHoursRepository;

private BusinessHours mondayHours;
private BusinessHours sundayHours;

@BeforeEach
void setUp() {
businessHoursRepository.deleteAll();

mondayHours = BusinessHours.builder()
.dayOfWeek(DayOfWeek.MONDAY)
.openTime(LocalTime.of(9, 0))
.closeTime(LocalTime.of(18, 0))
.breakStartTime(LocalTime.of(13, 0))
.breakEndTime(LocalTime.of(14, 0))
.isOpen(true)
.build();

sundayHours = BusinessHours.builder()
.dayOfWeek(DayOfWeek.SUNDAY)
.openTime(LocalTime.of(9, 0))
.closeTime(LocalTime.of(18, 0))
.isOpen(false)
.build();

businessHoursRepository.save(mondayHours);
businessHoursRepository.save(sundayHours);
}

@Test
void testFindByDayOfWeek() {
Optional<BusinessHours> found = businessHoursRepository
.findByDayOfWeek(DayOfWeek.MONDAY);

assertThat(found).isPresent();
assertThat(found.get().getDayOfWeek()).isEqualTo(DayOfWeek.MONDAY);
assertThat(found.get().getOpenTime()).isEqualTo(LocalTime.of(9, 0));
assertThat(found.get().getCloseTime()).isEqualTo(LocalTime.of(18, 0));
}

@Test
void testFindByDayOfWeek_Sunday() {
Optional<BusinessHours> found = businessHoursRepository
.findByDayOfWeek(DayOfWeek.SUNDAY);

assertThat(found).isPresent();
assertThat(found.get().getIsOpen()).isFalse();
}

@Test
void testFindByDayOfWeek_NotFound() {
Optional<BusinessHours> found = businessHoursRepository
.findByDayOfWeek(DayOfWeek.SATURDAY);

assertThat(found).isEmpty();
}

@Test
void testSaveAndRetrieve() {
BusinessHours wednesdayHours = BusinessHours.builder()
.dayOfWeek(DayOfWeek.WEDNESDAY)
.openTime(LocalTime.of(8, 30))
.closeTime(LocalTime.of(17, 30))
.breakStartTime(LocalTime.of(12, 30))
.breakEndTime(LocalTime.of(13, 30))
.isOpen(true)
.build();

BusinessHours saved = businessHoursRepository.save(wednesdayHours);

assertThat(saved.getId()).isNotNull();
assertThat(saved.getDayOfWeek()).isEqualTo(DayOfWeek.WEDNESDAY);
assertThat(saved.getOpenTime()).isEqualTo(LocalTime.of(8, 30));
assertThat(saved.getCloseTime()).isEqualTo(LocalTime.of(17, 30));
}

@Test
void testFindAll() {
assertThat(businessHoursRepository.findAll()).hasSize(2);
}
}
Loading