Skip to content
This repository was archived by the owner on Nov 23, 2025. It is now read-only.

Dev#5

Merged
RandithaK merged 34 commits into
mainfrom
dev
Nov 8, 2025
Merged

Dev#5
RandithaK merged 34 commits into
mainfrom
dev

Conversation

@RandithaK

Copy link
Copy Markdown
Member

No description provided.

ChamodiSandunika and others added 30 commits October 31, 2025 15:19
…Config for appointment availability endpoint
RandithaK and others added 4 commits November 6, 2025 11:23
feat: Enhance appointment filtering and role-based access in services and repositories
feat: Add GitHub Actions workflows for building, packaging, and deploying the Appointment Service to Kubernetes
Copilot AI review requested due to automatic review settings November 8, 2025 11:17
@coderabbitai

coderabbitai Bot commented Nov 8, 2025

Copy link
Copy Markdown

Warning

Rate limit exceeded

@RandithaK has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 25 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f171a90 and f567fcc.

📒 Files selected for processing (47)
  • .github/workflows/build.yaml (1 hunks)
  • .github/workflows/deploy.yaml (1 hunks)
  • Dockerfile (1 hunks)
  • IMPLEMENTATION_SUMMARY.md (1 hunks)
  • README.md (1 hunks)
  • appointment-service/pom.xml (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/config/DataSeeder.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/config/GatewayHeaderFilter.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/config/OpenApiConfig.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/config/SecurityConfig.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/controller/AppointmentController.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/controller/ServiceTypeController.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/request/AppointmentRequestDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/request/AppointmentUpdateDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/request/ServiceTypeRequestDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/request/StatusUpdateDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/AppointmentResponseDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/AppointmentSummaryDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/AvailabilityResponseDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/CalendarDayDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/CalendarResponseDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/CalendarStatisticsDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/ScheduleItemDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/ScheduleResponseDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/ServiceTypeResponseDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/dto/response/TimeSlotDto.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/entity/Appointment.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/entity/BusinessHours.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/entity/Holiday.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/entity/ServiceBay.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/entity/ServiceType.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/exception/AppointmentNotFoundException.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/exception/ErrorResponse.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/exception/GlobalExceptionHandler.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/exception/InvalidStatusTransitionException.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/exception/UnauthorizedAccessException.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/repository/AppointmentRepository.java (2 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/repository/BusinessHoursRepository.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/repository/HolidayRepository.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/repository/ServiceBayRepository.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/repository/ServiceTypeRepository.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/service/AppointmentService.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/service/ServiceTypeService.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/service/impl/AppointmentServiceImpl.java (1 hunks)
  • appointment-service/src/main/java/com/techtorque/appointment_service/service/impl/ServiceTypeServiceImpl.java (1 hunks)
  • appointment-service/src/test/java/com/techtorque/appointment_service/AppointmentServiceApplicationTests.java (1 hunks)
  • appointment-service/src/test/resources/application-test.properties (1 hunks)
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements the Appointment Service from scratch, transforming it from 0% to 100% completion. The service handles appointment booking, scheduling, and management with comprehensive business logic including service types, service bays, business hours, and holiday management.

  • Complete implementation of all 15 API endpoints for appointment and service type management
  • Full business logic with validation for dates, times, business hours, holidays, and bay availability
  • Comprehensive data seeding with 10 service types, 4 service bays, business hours, holidays, and sample appointments
  • Role-based access control for customers, employees, and admins

Reviewed Changes

Copilot reviewed 47 out of 47 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
AppointmentServiceImpl.java Complete service implementation with 546 lines of business logic for appointments
ServiceTypeServiceImpl.java Service type CRUD operations with duplicate name validation
AppointmentController.java 9 REST endpoints for appointment management with role-based security
ServiceTypeController.java 6 REST endpoints for service type management (admin/employee only)
DataSeeder.java Comprehensive seed data with 421 lines covering all entities
AppointmentRepository.java 10 custom queries including native query for flexible filtering
ServiceTypeRepository.java Active/inactive filtering and category-based queries
ServiceBayRepository.java Active bay queries with ordering
BusinessHoursRepository.java Day-of-week based operating hours lookup
HolidayRepository.java Date-based holiday checking
GatewayHeaderFilter.java Enhanced to handle SUPER_ADMIN role mapping to ADMIN
SecurityConfig.java Added public endpoint for availability checking
OpenApiConfig.java Complete Swagger/OpenAPI documentation configuration
Entity classes 5 new entities (ServiceType, ServiceBay, BusinessHours, Holiday, updated Appointment)
DTO classes 13 DTOs for request/response handling
Exception classes 4 custom exceptions with global handler
Test configuration H2 test database setup with PostgreSQL compatibility
Docker & CI/CD Build, package, and deployment workflows
Documentation Comprehensive README and implementation summary

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

LocalDateTime aptStart = appointment.getRequestedDateTime();
LocalDateTime aptEnd = aptStart.plusMinutes(60);

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same hardcoded 60-minute duration issue when checking bay availability. This method is used in the availability checking endpoint and doesn't consider the actual duration of existing appointments, which can range from 30 to 300 minutes based on service type. Should retrieve and use the actual service type duration for each appointment.

Copilot uses AI. Check for mistakes.
Comment on lines +322 to +327
if (businessHours.getBreakStartTime() != null && businessHours.getBreakEndTime() != null) {
if (!time.isBefore(businessHours.getBreakStartTime()) &&
time.isBefore(businessHours.getBreakEndTime())) {
throw new IllegalArgumentException("Cannot book appointment during break time");
}
}

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete validation for appointments that span the break time. The current check only validates if the appointment starts during the break (lines 323-324), but doesn't prevent appointments that start before the break and would continue into it. For example, a 90-minute appointment starting at 11:30 AM would pass this validation but would overlap with the 12:00-1:00 PM lunch break.

Should add:

LocalDateTime appointmentEnd = dateTime.plusMinutes(durationMinutes);
if (time.isBefore(businessHours.getBreakEndTime()) && 
    appointmentEnd.toLocalTime().isAfter(businessHours.getBreakStartTime())) {
  throw new IllegalArgumentException("Appointment would overlap with break time");
}

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +205 to +207
- Customer IDs: `00000000-0000-0000-0000-000000000101`, `00000000-0000-0000-0000-000000000102`
- Employee IDs: `00000000-0000-0000-0000-000000000003-005`
- Vehicle IDs: `VEH-001` to `VEH-004`

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation inconsistency: The README states shared constants are "Customer IDs: 00000000-0000-0000-0000-000000000101, 00000000-0000-0000-0000-000000000102" and "Employee IDs: 00000000-0000-0000-0000-000000000003-005", but the actual DataSeeder.java file uses simple string values like "customer", "testuser", and "employee". The documentation should be updated to reflect the actual implementation.

Suggested change
- Customer IDs: `00000000-0000-0000-0000-000000000101`, `00000000-0000-0000-0000-000000000102`
- Employee IDs: `00000000-0000-0000-0000-000000000003-005`
- Vehicle IDs: `VEH-001` to `VEH-004`
- Customer IDs: `"customer"`, `"testuser"`
- Employee IDs: `"employee"`
- Vehicle IDs: `"VEH-001"`, `"VEH-002"`, `"VEH-003"`, `"VEH-004"`

Copilot uses AI. Check for mistakes.
Comment thread IMPLEMENTATION_SUMMARY.md
Comment on lines +225 to +238
```java
// User IDs (from Auth Service)
CUSTOMER_1_ID = "00000000-0000-0000-0000-000000000101"
CUSTOMER_2_ID = "00000000-0000-0000-0000-000000000102"
EMPLOYEE_1_ID = "00000000-0000-0000-0000-000000000003"
EMPLOYEE_2_ID = "00000000-0000-0000-0000-000000000004"
EMPLOYEE_3_ID = "00000000-0000-0000-0000-000000000005"

// Vehicle IDs (for Vehicle Service)
VEHICLE_1_ID = "VEH-001"
VEHICLE_2_ID = "VEH-002"
VEHICLE_3_ID = "VEH-003"
VEHICLE_4_ID = "VEH-004"
```

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation inconsistency: The IMPLEMENTATION_SUMMARY.md states that the shared constants are UUID values like "00000000-0000-0000-0000-000000000101" for customers and "00000000-0000-0000-0000-000000000003" for employees, but the actual DataSeeder.java implementation uses simple string values like "customer", "testuser", and "employee". The documentation should be updated to match the actual implementation.

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +84
if (userRoles.contains("ADMIN") || userRoles.contains("EMPLOYEE")) {
appointments = appointmentRepository.findAll();
} else if (userRoles.contains("EMPLOYEE")) {
appointments = appointmentRepository.findByAssignedEmployeeIdAndRequestedDateTimeBetween(
userId, LocalDateTime.now().minusYears(1), LocalDateTime.now().plusYears(1));
} else {
appointments = appointmentRepository.findByCustomerIdOrderByRequestedDateTimeDesc(userId);
}

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant and unreachable conditional logic detected. Line 77 checks if userRoles contains "ADMIN" OR "EMPLOYEE", which will match if either is present. Line 79 then checks if userRoles contains "EMPLOYEE" - but this will never be reached when the user has only the EMPLOYEE role, since line 77 would have already handled it. This means employees will incorrectly receive ALL appointments instead of just their assigned ones.

The correct logic should be:

if (userRoles.contains("ADMIN")) {
  appointments = appointmentRepository.findAll();
} else if (userRoles.contains("EMPLOYEE")) {
  appointments = appointmentRepository.findByAssignedEmployeeIdAndRequestedDateTimeBetween(
      userId, LocalDateTime.now().minusYears(1), LocalDateTime.now().plusYears(1));
} else {
  appointments = appointmentRepository.findByCustomerIdOrderByRequestedDateTimeDesc(userId);
}

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +31
public static final String EMPLOYEE_2_ID = "employee";
public static final String EMPLOYEE_3_ID = "employee";

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three EMPLOYEE constants are set to the same value "employee". This appears to be a copy-paste error. EMPLOYEE_2_ID and EMPLOYEE_3_ID should have unique values for proper employee identification across the system. This will cause issues when trying to distinguish between different employees for appointment assignments.

Suggested change
public static final String EMPLOYEE_2_ID = "employee";
public static final String EMPLOYEE_3_ID = "employee";
public static final String EMPLOYEE_2_ID = "employee2";
public static final String EMPLOYEE_3_ID = "employee3";

Copilot uses AI. Check for mistakes.
Comment on lines +157 to +160
validateAppointmentDateTime(dto.getRequestedDateTime(), 60);
appointment.setRequestedDateTime(dto.getRequestedDateTime());
String newBayId = findAvailableBay(dto.getRequestedDateTime(), 60);
appointment.setAssignedBayId(newBayId);

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded duration of 60 minutes is used when updating an appointment, regardless of the actual service type's estimated duration. This should retrieve the service type's duration from the appointment entity or use the original service type's estimatedDurationMinutes to ensure accurate bay availability checking and time slot validation.

Copilot uses AI. Check for mistakes.
boolean isAvailable = bayAppointments.stream()
.noneMatch(apt -> {
LocalDateTime aptStart = apt.getRequestedDateTime();
LocalDateTime aptEnd = aptStart.plusMinutes(60);

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded appointment duration of 60 minutes when checking for bay availability conflicts. This doesn't account for the actual duration of existing appointments, which could vary (30 min for oil changes, 180 min for full service, etc.). Should use the actual service type's estimated duration from the appointment or look it up from the service type repository.

Copilot uses AI. Check for mistakes.
if (maxConfirmationOpt.isPresent() && maxConfirmationOpt.get() != null) {
String maxConfirmation = maxConfirmationOpt.get();
String numberPart = maxConfirmation.substring(prefix.length());
nextNumber = Integer.parseInt(numberPart) + 1;

Copilot AI Nov 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential uncaught 'java.lang.NumberFormatException'.

Copilot uses AI. Check for mistakes.
@RandithaK
RandithaK merged commit eec3fcc into main Nov 8, 2025
14 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants