species service validation (#317)

* fix species-service validation

* add grooming for hamster, other

* expand reptile and other services
This commit is contained in:
2026-04-15 16:25:14 -06:00
committed by GitHub
parent e23f9f9318
commit e87bb7bebf
3 changed files with 24 additions and 36 deletions

View File

@@ -127,8 +127,6 @@ public class AppointmentService {
} }
} }
validateSpeciesServiceCompatibility(pet, service);
validateStoreAccess(store.getStoreId(), authenticatedUser); validateStoreAccess(store.getStoreId(), authenticatedUser);
validatePetServiceCompatibility(pet, service); validatePetServiceCompatibility(pet, service);
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), null); validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), null);
@@ -387,32 +385,6 @@ public class AppointmentService {
return true; return true;
} }
private void validateSpeciesServiceCompatibility(Pet pet, com.petshop.backend.entity.Service service) {
if (pet == null || service == null) return;
String species = pet.getPetSpecies();
if (species == null) return;
String serviceName = service.getServiceName().toLowerCase();
switch (species.toLowerCase()) {
case "bird":
if (!serviceName.contains("wing clipping") && !serviceName.contains("beak and nail")) {
throw new IllegalArgumentException(
"Service '" + service.getServiceName() + "' is not available for birds. " +
"Allowed services: Wing Clipping, Beak and Nail Care.");
}
break;
case "fish":
if (!serviceName.contains("aquarium health")) {
throw new IllegalArgumentException(
"Service '" + service.getServiceName() + "' is not available for fish. " +
"Allowed service: Aquarium Health Check.");
}
break;
default:
break;
}
}
private void validateStoreAccess(Long requestedStoreId, User user) { private void validateStoreAccess(Long requestedStoreId, User user) {
if (user.getRole() != User.Role.STAFF) { if (user.getRole() != User.Role.STAFF) {
return; return;

View File

@@ -0,0 +1,14 @@
DELETE FROM service_species WHERE serviceId = 2 AND species = 'Bird';
INSERT INTO service_species (serviceId, species) VALUES
(1, 'Guinea Pig'),
(1, 'Hamster'),
(1, 'Other'),
(2, 'Reptile'),
(2, 'Other'),
(3, 'Reptile'),
(3, 'Other'),
(4, 'Reptile'),
(4, 'Other'),
(5, 'Reptile'),
(5, 'Other');

View File

@@ -20,20 +20,22 @@ const SPECIES_BREEDS = {
Other: ["Other"], Other: ["Other"],
}; };
// Explicit allowlists for species with restricted service availability. const SPECIES_EXCLUSIVE_SERVICES = {
// Species not listed here may use all services.
const SPECIES_SERVICE_ALLOWLIST = {
Bird: ["wing clipping", "beak and nail"], Bird: ["wing clipping", "beak and nail"],
Fish: ["aquarium health"], Fish: ["aquarium health"],
}; };
function getAvailableServices(services, species) { function getAvailableServices(services, species) {
if (!species) return services; if (!species) return services;
const allowlist = SPECIES_SERVICE_ALLOWLIST[species]; return services.filter((s) => {
if (!allowlist) return services; const name = s.serviceName.toLowerCase();
return services.filter((s) => for (const [exclusiveSpecies, keywords] of Object.entries(SPECIES_EXCLUSIVE_SERVICES)) {
allowlist.some((kw) => s.serviceName.toLowerCase().includes(kw)) if (exclusiveSpecies !== species && keywords.some((kw) => name.includes(kw))) {
); return false;
}
}
return true;
});
} }
const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];