diff --git a/src/main/java/com/MeetMate/appointment/Appointment.java b/src/main/java/com/MeetMate/appointment/Appointment.java index f940601..9da331c 100644 --- a/src/main/java/com/MeetMate/appointment/Appointment.java +++ b/src/main/java/com/MeetMate/appointment/Appointment.java @@ -1,30 +1,28 @@ package com.MeetMate.appointment; import com.MeetMate.enums.AppointmentStatus; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.mongodb.core.mapping.Document; -import java.time.LocalDateTime; - @Document(collection = "appointments") @Data @NoArgsConstructor public class Appointment { - long id; - LocalDateTime from; - LocalDateTime to; - long companyID; - long clientID; - long assigneeID; -// Select Prompt → f.E. medical industry: Untersuchung, Operation - String description; - String location; - AppointmentStatus status; + private long id; + private String from; + private String to; + private long companyId; + private long clientId; + private long assigneeId; + // Select Prompt → f.E. medical industry: Untersuchung, Operation + private String description; + private String location; + private AppointmentStatus status; - public Appointment(long id, long companyID, long clientID) { + public Appointment(long id, long companyId) { this.id = id; - this.companyID = companyID; - this.clientID = clientID; + this.companyId = companyId; } } diff --git a/src/main/java/com/MeetMate/appointment/AppointmentConfig.java b/src/main/java/com/MeetMate/appointment/AppointmentConfig.java index 49cff69..dd5c441 100644 --- a/src/main/java/com/MeetMate/appointment/AppointmentConfig.java +++ b/src/main/java/com/MeetMate/appointment/AppointmentConfig.java @@ -10,7 +10,6 @@ // // @Bean // public CommandLineRunner run(AppointmentRepository appointmentRepository) throws Exception { -// System.out.println("Yeehaaaa"); // return args -> { // Appointment appointment = new Appointment(); // appointment.setId(1L); diff --git a/src/main/java/com/MeetMate/appointment/AppointmentController.java b/src/main/java/com/MeetMate/appointment/AppointmentController.java index 17036eb..8db5c42 100644 --- a/src/main/java/com/MeetMate/appointment/AppointmentController.java +++ b/src/main/java/com/MeetMate/appointment/AppointmentController.java @@ -1,30 +1,32 @@ package com.MeetMate.appointment; +import com.MeetMate.enums.AppointmentStatus; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.graphql.data.method.annotation.Argument; +import org.springframework.graphql.data.method.annotation.ContextValue; import org.springframework.graphql.data.method.annotation.MutationMapping; import org.springframework.graphql.data.method.annotation.QueryMapping; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMapping; -import java.lang.reflect.InaccessibleObjectException; -import java.util.Map; - @Controller @RequestMapping(path = "api/appointment") @RequiredArgsConstructor public class AppointmentController { + private final AppointmentService appointmentService; @QueryMapping - public Appointment getAppointment(@Argument long id) { + public Appointment getAppointment( + @ContextValue String token, + @Argument long id + ) { + token = token.substring(7); try { - return appointmentService.getAppointment(id); - + return appointmentService.getAppointment(token, id); } catch (Throwable t) { Class tc = t.getClass(); return null; @@ -48,25 +50,73 @@ public ResponseEntity createAppointment( // @Argument Select Prompt → f.E. medical industry: Untersuchung, Operation, @Argument String description, @Argument String location, - @Argument String status) { + @Argument String status + ) { try { - Map appointmentData = Map.of( - "from", from, - "to", to, - "assigneeId", assigneeId, - // "prompt", Select Prompt → f.E. medical industry: Untersuchung, Operation); - "description", description, - "location", location, - "status", status - ); - - appointmentService.createAppointment(companyId, clientId, appointmentData); + appointmentService.createAppointment(from, to, companyId, clientId, assigneeId, description, location, AppointmentStatus.valueOf(status)); return ResponseEntity.ok().build(); } catch (Throwable t) { Class tc = t.getClass(); - if (tc == InaccessibleObjectException.class) - return ResponseEntity.status(HttpStatus.PRECONDITION_FAILED).body("message: " + t.getMessage()); + + if (tc == EntityNotFoundException.class) + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("message: " + t.getMessage()); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("message: " + t.getMessage()); + } + } + + @MutationMapping + public ResponseEntity editAppointment( + @ContextValue String token, + @Argument long id, + @Argument String from, + @Argument String to, + @Argument long clientId, + @Argument long assigneeId, +// @Argument Select Prompt → f.E. medical industry: Untersuchung, Operation, + @Argument String description, + @Argument String location, + @Argument String status + ) { + token = token.substring(7); + try { + appointmentService.editAppointment(token, id, from, to, clientId, assigneeId, description, location, AppointmentStatus.valueOf(status)); + return ResponseEntity.ok().build(); + + } catch (Throwable t) { + Class tc = t.getClass(); + if (tc == EntityNotFoundException.class) + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("message: " + t.getMessage()); + + if (tc == IllegalStateException.class) + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("message: " + t.getMessage()); + + if (tc == IllegalArgumentException.class) + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("message: " + t.getMessage()); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("message: " + t.getMessage()); + } + } + + @MutationMapping + public ResponseEntity deleteAppointment( + @ContextValue String token, + @Argument long id + ) { + token = token.substring(7); + try { + appointmentService.deleteAppointment(token, id); + return ResponseEntity.ok().build(); + + } catch (Throwable t) { + Class tc = t.getClass(); + + if (tc == IllegalStateException.class) + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("message: " + t.getMessage()); + + if (tc == IllegalArgumentException.class) + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("message: " + t.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("message: " + t.getMessage()); } diff --git a/src/main/java/com/MeetMate/appointment/AppointmentService.java b/src/main/java/com/MeetMate/appointment/AppointmentService.java index 853ba2f..2bbe8c7 100644 --- a/src/main/java/com/MeetMate/appointment/AppointmentService.java +++ b/src/main/java/com/MeetMate/appointment/AppointmentService.java @@ -1,38 +1,120 @@ package com.MeetMate.appointment; import com.MeetMate.appointment.sequence.AppointmentSequenceService; +import com.MeetMate.company.Company; +import com.MeetMate.company.CompanyRepository; +import com.MeetMate.enums.AppointmentStatus; +import com.MeetMate.security.JwtService; +import com.MeetMate.user.User; +import com.MeetMate.user.UserRepository; import jakarta.persistence.EntityNotFoundException; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; -import java.lang.reflect.Field; -import java.util.Map; - @Service @RequiredArgsConstructor public class AppointmentService { private final AppointmentRepository appointmentRepository; private final AppointmentSequenceService appointmentSequenceService; + private final MongoTemplate mongoTemplate; + private final JwtService jwtService; + private final UserRepository userRepository; + private final CompanyRepository companyRepository; - public Appointment getAppointment(long id) { - return appointmentRepository.findAppointmentById(id) + public Appointment getAppointment(String token, long appointmentId) { + if (userNotInAppointment(token, appointmentId)) + throw new IllegalArgumentException("User is not eligible to edit this appointment"); + return appointmentRepository.findAppointmentById(appointmentId) .orElseThrow(() -> new EntityNotFoundException("Appointment not found")); } @Transactional - public void createAppointment(long companyId, long clientId, Map appointmentData) throws IllegalAccessException { + public void createAppointment(String from, String to, long companyId, long clientId, long assigneeId, String description, String location, AppointmentStatus status) { + //Check if IDs are valid + if (companyRepository.findCompanyById(companyId).isEmpty()) + throw new EntityNotFoundException("Company not found"); + if (clientId != 0 && userRepository.findUserById(clientId).isEmpty()) + throw new EntityNotFoundException("Client not found"); + if (assigneeId != 0 && userRepository.findUserById(assigneeId).isEmpty()) + throw new EntityNotFoundException("Assignee not found"); + long appointmentId = appointmentSequenceService.getCurrentValue(); - Appointment appointment = new Appointment(appointmentId, companyId, clientId); - Field[] fields = Appointment.class.getDeclaredFields(); - for(Field field : fields) { - field.setAccessible(true); - field.set(appointment, appointmentData.get(field.getName())); - } + Appointment appointment = new Appointment(appointmentId, companyId); + if (from != null && !from.isEmpty()) appointment.setFrom(from); + if (to != null && !to.isEmpty()) appointment.setTo(to); + if (clientId != 0) appointment.setClientId(clientId); + if (assigneeId != 0) appointment.setAssigneeId(assigneeId); + if (description != null && !description.isEmpty()) appointment.setDescription(description); + if (location != null && !location.isEmpty()) appointment.setLocation(location); + if (status != null) appointment.setStatus(status); appointmentRepository.save(appointment); appointmentSequenceService.incrementId(); } + + @Transactional + public void editAppointment(String token, long appointmentId, String from, String to, long clientId, long assigneeId, String description, String location, AppointmentStatus status) throws IllegalAccessException { + if (userNotInAppointment(token, appointmentId)) + throw new IllegalArgumentException("User is not eligible to edit this appointment"); + + //Check if IDs are valid + if (clientId != 0 && userRepository.findUserById(clientId).isEmpty()) + throw new EntityNotFoundException("Client not found"); + if (assigneeId != 0 && userRepository.findUserById(assigneeId).isEmpty()) + throw new EntityNotFoundException("Assignee not found"); + + Query query = new Query(Criteria.where("appointmentId").is(appointmentId)); + Update update = new Update(); + + if (from != null && !from.isEmpty()) update.set("from", from); + if (to != null && !to.isEmpty()) update.set("to", to); + if (clientId != 0) update.set("clientId", clientId); + if (assigneeId != 0) update.set("assigneeId", assigneeId); + if (description != null && !description.isEmpty()) update.set("description", description); + if (location != null && !location.isEmpty()) update.set("location", location); + if (status != null) update.set("status", status); + + mongoTemplate.updateFirst(query, update, Company.class); + } + + @Transactional + public void deleteAppointment(String token, long appointmentId) { + if (userNotInAppointment(token, appointmentId)) + throw new IllegalArgumentException("User is not eligible to edit this appointment"); + Appointment appointment = appointmentRepository.findAppointmentById(appointmentId) + .orElseThrow(() -> new EntityNotFoundException("Appointment not found")); + + appointmentRepository.delete(appointment); + } + + private boolean userNotInAppointment(String token, long appointmentId) throws IllegalArgumentException { + String userEmail = jwtService.extractUserEmail(token); + User user = userRepository.findUserByEmail(userEmail) + .orElseThrow(() -> new EntityNotFoundException("User not found!")); + Appointment appointment = appointmentRepository.findAppointmentById(appointmentId) + .orElseThrow(() -> new EntityNotFoundException("Appointment not found!")); + + switch (user.getRole()) { + case COMPANY_OWNER, COMPANY_MEMBER -> { + if (appointment.getCompanyId() == user.getAssociatedCompany()) + return false; + } + case CLIENT -> { + if (appointment.getClientId() == user.getId()) + return false; + } + default -> { + throw new IllegalStateException("Role of user not found!"); + } + } + return true; + } + } diff --git a/src/main/resources/graphql/schema.graphqls b/src/main/resources/graphql/schema.graphqls index c5c80f6..8f32ba6 100644 --- a/src/main/resources/graphql/schema.graphqls +++ b/src/main/resources/graphql/schema.graphqls @@ -31,13 +31,29 @@ type Mutation { createAppointment( from: String, to: String, - companyID: ID!, - clientID: ID!, - assigneeID: ID, - # Select Prompt → f.E. medical industry: Untersuchung, Operation + companyId: ID!, + clientId: ID, + assigneeId: ID, +# description: String, - location: String - appointmentStatus: String + location: String, + status: String + ): String + + editAppointment( + id: ID!, + from: String, + to: String, + clientId: ID, + assigneeId: ID, + + description: String, + location: String, + status: String + ): String + + deleteAppointment( + id: ID! ): String } @@ -54,11 +70,11 @@ type Appointment { id: ID from: String to: String - companyID: ID - clientID: ID - assigneeID: ID + companyId: ID + clientId: ID + assigneeId: ID # Select Prompt → f.E. medical industry: Untersuchung, Operation description: String location: String - AppointmentStatus: String + Status: String } \ No newline at end of file