From 8f8aa1b8bb882f03840bf72b346afc13b7da18fb Mon Sep 17 00:00:00 2001 From: rrrrde1go Date: Sat, 21 Feb 2026 10:06:39 +0300 Subject: [PATCH] =?UTF-8?q?=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=202?= =?UTF-8?q?=20=D1=8D=D1=82=D0=B0=D0=BF=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nto/controller/BookingController.java | 134 +++--------------- .../nto/controller/EmployeeController.java | 27 ++-- .../nto/controller/dto/BookingCreateDto.java | 18 +++ .../nto/controller/dto/EmployeeDto.java | 32 +++++ .../example/nto/controller/dto/PlaceDto.java | 18 +++ .../java/com/example/nto/entity/Booking.java | 31 ++-- .../java/com/example/nto/entity/Employee.java | 36 ++--- .../java/com/example/nto/entity/Place.java | 20 +-- .../BookingAlreadyExistException.java | 7 + .../exception/EmployeeNotFoundException.java | 7 + .../nto/exception/PlaceNotFoundException.java | 7 + .../handler/GlobalExceptionHandler.java | 35 +++++ .../nto/repository/BookingRepository.java | 6 +- .../nto/repository/EmployeeRepository.java | 3 + .../example/nto/service/BookingService.java | 14 +- .../example/nto/service/EmployeeService.java | 8 +- .../com/example/nto/service/PlaceService.java | 10 -- .../nto/service/impl/BookingServiceImpl.java | 101 +++++++++---- .../nto/service/impl/EmployeeServiceImpl.java | 25 ++-- .../nto/service/impl/PlaceServiceImpl.java | 29 ---- 20 files changed, 295 insertions(+), 273 deletions(-) create mode 100644 src/main/java/com/example/nto/controller/dto/BookingCreateDto.java create mode 100644 src/main/java/com/example/nto/controller/dto/EmployeeDto.java create mode 100644 src/main/java/com/example/nto/controller/dto/PlaceDto.java create mode 100644 src/main/java/com/example/nto/exception/BookingAlreadyExistException.java create mode 100644 src/main/java/com/example/nto/exception/EmployeeNotFoundException.java create mode 100644 src/main/java/com/example/nto/exception/PlaceNotFoundException.java create mode 100644 src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java delete mode 100644 src/main/java/com/example/nto/service/PlaceService.java delete mode 100644 src/main/java/com/example/nto/service/impl/PlaceServiceImpl.java diff --git a/src/main/java/com/example/nto/controller/BookingController.java b/src/main/java/com/example/nto/controller/BookingController.java index f4b8c0a..80f885e 100644 --- a/src/main/java/com/example/nto/controller/BookingController.java +++ b/src/main/java/com/example/nto/controller/BookingController.java @@ -1,134 +1,32 @@ package com.example.nto.controller; -import com.example.nto.entity.Booking; -import com.example.nto.entity.Employee; -import com.example.nto.entity.Place; +import com.example.nto.controller.dto.BookingCreateDto; +import com.example.nto.controller.dto.PlaceDto; import com.example.nto.service.BookingService; -import com.example.nto.service.EmployeeService; -import com.example.nto.service.PlaceService; +import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.time.LocalDate; import java.util.*; -import java.util.stream.Collectors; - +@Validated @RestController -@RequestMapping("/api/{code}") +@RequestMapping("api") +@RequiredArgsConstructor public class BookingController { - private final EmployeeService employeeService; - private final BookingService bookingService; - private final PlaceService placeService; + private static BookingService bookingService; - public BookingController(EmployeeService employeeService, BookingService bookingService, PlaceService placeService) { - this.employeeService = employeeService; - this.bookingService = bookingService; - this.placeService = placeService; + @GetMapping("/{code}/booking") + @ResponseStatus(code = HttpStatus.OK) + public Map> getByDate(@PathVariable String code) { + return bookingService.getFreePLace(code); } - @GetMapping("/auth") - public ResponseEntity auth(@PathVariable String code) { - Optional employeeOpt = employeeService.findByCode(code); - if (employeeOpt.isPresent()) { - return ResponseEntity.ok().build(); - } else { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - } - @GetMapping("/info") - public ResponseEntity> info(@PathVariable String code) { - Optional employeeOpt = employeeService.findByCode(code); - if (employeeOpt.isEmpty()) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - - Employee employee = employeeOpt.get(); - Map response = new HashMap<>(); - response.put("name", employee.getName()); - response.put("photoUrl", employee.getPhotoUrl()); - - Map>> bookingsMap = new HashMap<>(); - List bookingList = bookingService.getBookingsByEmployee(employee); - - for (Booking b : bookingList) { - String dateKey = b.getDate().toString(); - Map bookingData = new HashMap<>(); - bookingData.put("id", b.getId()); - bookingData.put("place", b.getPlace().getPlace()); - - bookingsMap.computeIfAbsent(dateKey, k -> new ArrayList<>()).add(bookingData); - } - - response.put("booking", bookingsMap); - return ResponseEntity.ok(response); - } - - @GetMapping("/booking") - public ResponseEntity>>> availableBooking(@PathVariable String code) { - Optional employeeOpt = employeeService.findByCode(code); - if (employeeOpt.isEmpty()) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - - Map>> result = new LinkedHashMap<>(); - LocalDate today = LocalDate.now(); - List allPlaces = placeService.getAllPlaces(); - - for (int i = 0; i < 4; i++) { - LocalDate date = today.plusDays(i); - List bookings = bookingService.getBookingsByDate(date); - - Set bookedPlaceIds = bookings.stream() - .map(b -> b.getPlace().getId()) - .collect(Collectors.toSet()); - - List> available = allPlaces.stream() - .filter(p -> !bookedPlaceIds.contains(p.getId())) - .map(p -> { - Map m = new HashMap<>(); - m.put("id", p.getId()); - m.put("place", p.getPlace()); - return m; - }) - .collect(Collectors.toList()); - - result.put(date.toString(), available); - } - - return ResponseEntity.ok(result); - } - - @PostMapping("/book") - public ResponseEntity book(@PathVariable String code, @RequestBody Map body) { - Optional employeeOpt = employeeService.findByCode(code); - if (employeeOpt.isEmpty()) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - Employee employee = employeeOpt.get(); - - try { - String dateStr = body.get("date"); - String placeIdStr = body.getOrDefault("placeID", - body.getOrDefault("placeId", - body.getOrDefault("place", null))); - - if (dateStr == null || placeIdStr == null) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); - } - - LocalDate date = LocalDate.parse(dateStr); - Long placeId = Long.parseLong(placeIdStr); - Place place = placeService.getPlaceById(placeId); - - if (bookingService.getBookingByEmployeeAndDate(employee, date).isPresent()) { - return ResponseEntity.status(HttpStatus.CONFLICT).build(); - } - - if (bookingService.getBookingByDateAndPlace(date, place).isPresent()) { - return ResponseEntity.status(HttpStatus.CONFLICT).build(); - } - - bookingService.createBooking(employee, place, date); - return ResponseEntity.status(HttpStatus.CREATED).build(); - - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); - } + @GetMapping("/{code}/book") + @ResponseStatus(code = HttpStatus.CREATED) + public void create(@PathVariable String code, @RequestBody BookingCreateDto bookingCreateDto) { + bookingService.create(code, bookingCreateDto); } } diff --git a/src/main/java/com/example/nto/controller/EmployeeController.java b/src/main/java/com/example/nto/controller/EmployeeController.java index 527340c..ada1246 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -1,30 +1,27 @@ package com.example.nto.controller; -import com.example.nto.entity.Employee; +import com.example.nto.controller.dto.EmployeeDto; import com.example.nto.service.EmployeeService; +import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.Optional; @RestController -@RequestMapping("/api/employee") +@RequestMapping("api") +@RequiredArgsConstructor public class EmployeeController { - private final EmployeeService employeeService; - public EmployeeController(EmployeeService employeeService) { - this.employeeService = employeeService; + @GetMapping("/{code}/auth") + @ResponseStatus(code = HttpStatus.OK) + public void login(@PathVariable String code) { + employeeService.auth(code); } - @GetMapping("/{code}") - public ResponseEntity getEmployeeByCode(@PathVariable String code) { - Optional employeeOpt = employeeService.findByCode(code); - if (employeeOpt.isPresent()) { - return ResponseEntity.ok(employeeOpt.get()); - } else { - return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); - } + @GetMapping("/{code}/info") + @ResponseStatus(code = HttpStatus.OK) + public EmployeeDto getByCode(@PathVariable String code) { + return employeeService.getByCode(code); } } diff --git a/src/main/java/com/example/nto/controller/dto/BookingCreateDto.java b/src/main/java/com/example/nto/controller/dto/BookingCreateDto.java new file mode 100644 index 0000000..6bc3e66 --- /dev/null +++ b/src/main/java/com/example/nto/controller/dto/BookingCreateDto.java @@ -0,0 +1,18 @@ +package com.example.nto.controller.dto; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.*; + +import java.time.LocalDate; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class BookingCreateDto { + @NotNull + private LocalDate date; + @Positive + private long placeId; +} diff --git a/src/main/java/com/example/nto/controller/dto/EmployeeDto.java b/src/main/java/com/example/nto/controller/dto/EmployeeDto.java new file mode 100644 index 0000000..645dd3c --- /dev/null +++ b/src/main/java/com/example/nto/controller/dto/EmployeeDto.java @@ -0,0 +1,32 @@ +package com.example.nto.controller.dto; + + +import com.example.nto.entity.Booking; +import com.example.nto.entity.Employee; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.util.Map; +import java.util.TreeMap; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EmployeeDto { + private String name; + private String photoUrl; + private Map booking; + + public static EmployeeDto toDto(Employee employee) { + Map dtoTreeMap = new TreeMap<>(); + for (Booking booking : employee.getBookingList()) { + dtoTreeMap.put(booking.getDate(), PlaceDto.toDto(booking.getPlace())); + } + + return new EmployeeDto(employee.getName(), employee.getPhotoUrl(), dtoTreeMap); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/nto/controller/dto/PlaceDto.java b/src/main/java/com/example/nto/controller/dto/PlaceDto.java new file mode 100644 index 0000000..ac67aba --- /dev/null +++ b/src/main/java/com/example/nto/controller/dto/PlaceDto.java @@ -0,0 +1,18 @@ +package com.example.nto.controller.dto; + +import com.example.nto.entity.Place; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PlaceDto { + private long id; + private String place; + + public static PlaceDto toDto(Place place){return new PlaceDto(place.getId(), place.getPlace());} +} diff --git a/src/main/java/com/example/nto/entity/Booking.java b/src/main/java/com/example/nto/entity/Booking.java index d4dd146..d0e04ba 100644 --- a/src/main/java/com/example/nto/entity/Booking.java +++ b/src/main/java/com/example/nto/entity/Booking.java @@ -1,42 +1,35 @@ package com.example.nto.entity; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.time.LocalDate; +@Data @Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor @Table(name = "booking") -@JsonIgnoreProperties({"hibernateLazyInitializer"}) public class Booking { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; + @Column(name = "date") private LocalDate date; - @ManyToOne(fetch = FetchType.EAGER) + @ManyToOne(targetEntity = Place.class, fetch = FetchType.LAZY) @JoinColumn(name = "place_id") private Place place; - @ManyToOne(fetch = FetchType.EAGER) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "employee_id") private Employee employee; - public Booking() {} - public Booking(Employee employee, Place place, LocalDate date) { - this.employee = employee; - this.place = place; - this.date = date; - } - - public long getId() { return id; } - public void setId(long id) { this.id = id; } - public LocalDate getDate() { return date; } - public void setDate(LocalDate date) { this.date = date; } - public Place getPlace() { return place; } - public void setPlace(Place place) { this.place = place; } - public Employee getEmployee() { return employee; } - public void setEmployee(Employee employee) { this.employee = employee; } } diff --git a/src/main/java/com/example/nto/entity/Employee.java b/src/main/java/com/example/nto/entity/Employee.java index b1a34ef..6bf2fa1 100644 --- a/src/main/java/com/example/nto/entity/Employee.java +++ b/src/main/java/com/example/nto/entity/Employee.java @@ -1,11 +1,18 @@ package com.example.nto.entity; -import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; -import java.util.ArrayList; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.util.List; +@Data @Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor @Table(name = "employee") public class Employee { @@ -13,33 +20,16 @@ public class Employee { @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; + @Column(name = "name") private String name; - @Column(unique = true) + @Column(name = "code") private String code; + @Column(name = "photo_url") private String photoUrl; @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @JsonIgnore - private List bookingList = new ArrayList<>(); + private List bookingList; - public Employee() {} - - public Employee(String name, String code, String photoUrl) { - this.name = name; - this.code = code; - this.photoUrl = photoUrl; - } - - public long getId() { return id; } - public void setId(long id) { this.id = id; } - public String getName() { return name; } - public void setName(String name) { this.name = name; } - public String getCode() { return code; } - public void setCode(String code) { this.code = code; } - public String getPhotoUrl() { return photoUrl; } - public void setPhotoUrl(String photoUrl) { this.photoUrl = photoUrl; } - public List getBookingList() { return bookingList; } - public void setBookingList(List bookingList) { this.bookingList = bookingList; } } diff --git a/src/main/java/com/example/nto/entity/Place.java b/src/main/java/com/example/nto/entity/Place.java index 0981a3a..c266212 100644 --- a/src/main/java/com/example/nto/entity/Place.java +++ b/src/main/java/com/example/nto/entity/Place.java @@ -1,23 +1,23 @@ package com.example.nto.entity; import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +@Data @Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor @Table(name = "place") public class Place { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + private long id; - @Column(name = "place_name", nullable = false, unique = true) + @Column(name = "place_name") private String place; - - public Place() {} - public Place(String place) { this.place = place; } - - public Long getId() { return id; } - public void setId(Long id) { this.id = id; } - public String getPlace() { return place; } - public void setPlace(String place) { this.place = place; } } diff --git a/src/main/java/com/example/nto/exception/BookingAlreadyExistException.java b/src/main/java/com/example/nto/exception/BookingAlreadyExistException.java new file mode 100644 index 0000000..2748341 --- /dev/null +++ b/src/main/java/com/example/nto/exception/BookingAlreadyExistException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class BookingAlreadyExistException extends RuntimeException { + public BookingAlreadyExistException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/EmployeeNotFoundException.java b/src/main/java/com/example/nto/exception/EmployeeNotFoundException.java new file mode 100644 index 0000000..d427077 --- /dev/null +++ b/src/main/java/com/example/nto/exception/EmployeeNotFoundException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class EmployeeNotFoundException extends RuntimeException { + public EmployeeNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/PlaceNotFoundException.java b/src/main/java/com/example/nto/exception/PlaceNotFoundException.java new file mode 100644 index 0000000..2560027 --- /dev/null +++ b/src/main/java/com/example/nto/exception/PlaceNotFoundException.java @@ -0,0 +1,7 @@ +package com.example.nto.exception; + +public class PlaceNotFoundException extends RuntimeException { + public PlaceNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..c2c496f --- /dev/null +++ b/src/main/java/com/example/nto/exception/handler/GlobalExceptionHandler.java @@ -0,0 +1,35 @@ +package com.example.nto.exception.handler; + +import com.example.nto.exception.BookingAlreadyExistException; +import com.example.nto.exception.EmployeeNotFoundException; +import com.example.nto.exception.PlaceNotFoundException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(EmployeeNotFoundException.class) + public ResponseEntity handleEmployeeNotFoundException(EmployeeNotFoundException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED); + } + + @ExceptionHandler(BookingAlreadyExistException.class) + public ResponseEntity handleBookingAlreadyExistException(BookingAlreadyExistException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT); + } + + @ExceptionHandler(PlaceNotFoundException.class) + public ResponseEntity handlePlaceNotFoundException(PlaceNotFoundException e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handlerGenericException(Exception e) { + return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST); + } + + + +} diff --git a/src/main/java/com/example/nto/repository/BookingRepository.java b/src/main/java/com/example/nto/repository/BookingRepository.java index c6fc3eb..7d4093b 100644 --- a/src/main/java/com/example/nto/repository/BookingRepository.java +++ b/src/main/java/com/example/nto/repository/BookingRepository.java @@ -10,9 +10,9 @@ import java.util.List; import java.util.Optional; public interface BookingRepository extends JpaRepository { - List findByEmployee(Employee employee); - List findByDate(LocalDate date); + List findByDateBetween(LocalDate start, LocalDate end); + Optional findByDateAndPlace(LocalDate date, Place place); - Optional findByEmployeeAndDate(Employee employee, LocalDate date); + Optional findByDateAndEmployee(LocalDate date, Employee employee); } diff --git a/src/main/java/com/example/nto/repository/EmployeeRepository.java b/src/main/java/com/example/nto/repository/EmployeeRepository.java index 1a4f77a..d845a04 100644 --- a/src/main/java/com/example/nto/repository/EmployeeRepository.java +++ b/src/main/java/com/example/nto/repository/EmployeeRepository.java @@ -1,9 +1,12 @@ package com.example.nto.repository; import com.example.nto.entity.Employee; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; + import java.util.Optional; public interface EmployeeRepository extends JpaRepository { + @EntityGraph(attributePaths = {"bookingList", "bookingList.place"}) Optional findByCode(String code); } diff --git a/src/main/java/com/example/nto/service/BookingService.java b/src/main/java/com/example/nto/service/BookingService.java index fe191ea..a382837 100644 --- a/src/main/java/com/example/nto/service/BookingService.java +++ b/src/main/java/com/example/nto/service/BookingService.java @@ -1,19 +1,15 @@ package com.example.nto.service; +import com.example.nto.controller.dto.BookingCreateDto; +import com.example.nto.controller.dto.PlaceDto; import com.example.nto.entity.Booking; -import com.example.nto.entity.Employee; -import com.example.nto.entity.Place; import java.time.LocalDate; import java.util.List; -import java.util.Optional; +import java.util.Map; public interface BookingService { - List getBookingsByEmployee(Employee employee); - List getBookingsByDate(LocalDate date); - Optional getBookingByDateAndPlace(LocalDate date, Place place); + Map> getFreePLace(String code); - Optional getBookingByEmployeeAndDate(Employee employee, LocalDate date); - - Booking createBooking(Employee employee, Place place, LocalDate date); + Booking create(String code, BookingCreateDto bookingCreateDto); } diff --git a/src/main/java/com/example/nto/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java index a300e34..e5b41a4 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -1,8 +1,8 @@ package com.example.nto.service; -import com.example.nto.entity.Employee; -import java.util.Optional; +import com.example.nto.controller.dto.EmployeeDto; public interface EmployeeService { - Optional findByCode(String code); -} + EmployeeDto getByCode(String code); + void auth(String code); +} \ No newline at end of file diff --git a/src/main/java/com/example/nto/service/PlaceService.java b/src/main/java/com/example/nto/service/PlaceService.java deleted file mode 100644 index 37e28ac..0000000 --- a/src/main/java/com/example/nto/service/PlaceService.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.nto.service; - -import com.example.nto.entity.Place; - -import java.util.List; - -public interface PlaceService { - List getAllPlaces(); - Place getPlaceById(Long id); -} diff --git a/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java b/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java index 2091f53..583a7ba 100644 --- a/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java @@ -1,51 +1,102 @@ package com.example.nto.service.impl; +import com.example.nto.controller.dto.BookingCreateDto; +import com.example.nto.controller.dto.PlaceDto; import com.example.nto.entity.Booking; import com.example.nto.entity.Employee; import com.example.nto.entity.Place; +import com.example.nto.exception.BookingAlreadyExistException; +import com.example.nto.exception.EmployeeNotFoundException; +import com.example.nto.exception.PlaceNotFoundException; import com.example.nto.repository.BookingRepository; +import com.example.nto.repository.EmployeeRepository; +import com.example.nto.repository.PlaceRepository; import com.example.nto.service.BookingService; +import com.example.nto.service.EmployeeService; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; -import java.util.List; -import java.util.Optional; +import java.time.ZoneId; +import java.util.*; +import java.util.stream.Collectors; @Service +@RequiredArgsConstructor public class BookingServiceImpl implements BookingService { private final BookingRepository bookingRepository; + private final EmployeeRepository employeeRepository; + private final PlaceRepository placeRepository; + private final EmployeeService employeeService; - public BookingServiceImpl(BookingRepository bookingRepository) { - this.bookingRepository = bookingRepository; + @Value("${booking.days-ahead}") + private int daysAhead; + + @Override + @Transactional(readOnly = true) + public Map> getFreePLace(String code) { + employeeService.auth(code); + + List allPlaces = placeRepository.findAll(); + + LocalDate today = LocalDate.now(ZoneId.systemDefault()); + LocalDate end = today.plusDays(daysAhead); + + List bookings = bookingRepository.findByDateBetween(today, end); + + Map> busyByDate = bookings.stream() + .collect(Collectors.groupingBy(Booking::getDate, Collectors.mapping(b -> b.getPlace().getId(), Collectors.toSet()))); + + + Map> result = new LinkedHashMap<>(); + + for (int i = 0; i <= daysAhead; i++){ + LocalDate currentDate = today.plusDays(i); + Set busyPlaces = busyByDate.getOrDefault(currentDate, Collections.emptySet()); + + List freePlaces = allPlaces.stream() + .filter(place -> busyPlaces.contains(place.getId())) + .map(place -> new PlaceDto(place.getId(), place.getPlace())) + .toList(); + result.put(currentDate, freePlaces); + } + + return result; } @Override - public List getBookingsByEmployee(Employee employee) { - return bookingRepository.findByEmployee(employee); - } + @Transactional + public Booking create(String code, BookingCreateDto bookingCreateDto) { + LocalDate date = bookingCreateDto.getDate(); + LocalDate today = LocalDate.now(ZoneId.systemDefault()); + if (date.isBefore(today) || date.isAfter(today.plusDays(daysAhead))) { + throw new IllegalArgumentException("Date is out of booking window"); + } - @Override - public List getBookingsByDate(LocalDate date) { - return bookingRepository.findByDate(date); - } + Employee employee = employeeRepository.findByCode(code) + .orElseThrow(() -> new EmployeeNotFoundException("Employee with " + code + " code not found!")); - @Override - public Optional getBookingByDateAndPlace(LocalDate date, Place place) { - return bookingRepository.findByDateAndPlace(date, place); - } + long placeId = bookingCreateDto.getPlaceId(); + Place place = placeRepository.findById(placeId) + .orElseThrow(() -> new PlaceNotFoundException("Place with " + placeId + " id not found!")); - @Override - public Optional getBookingByEmployeeAndDate(Employee employee, LocalDate date) { - return bookingRepository.findByEmployeeAndDate(employee, date); - } + if (bookingRepository.findByDateAndPlace(date, place).isPresent()) { + throw new BookingAlreadyExistException("Booking already exists"); + } + + if (bookingRepository.findByDateAndEmployee(date, employee).isPresent()) { + throw new BookingAlreadyExistException("This employee already has another booking on " + date); + } + + Booking booking = Booking.builder() + .date(date) + .employee(employee) + .place(place) + .build(); - @Override - public Booking createBooking(Employee employee, Place place, LocalDate date) { - Booking booking = new Booking(); - booking.setEmployee(employee); - booking.setPlace(place); - booking.setDate(date); return bookingRepository.save(booking); } } diff --git a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java index 6939037..07cd2af 100644 --- a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java @@ -1,22 +1,31 @@ package com.example.nto.service.impl; -import com.example.nto.entity.Employee; +import com.example.nto.controller.dto.EmployeeDto; +import com.example.nto.exception.EmployeeNotFoundException; import com.example.nto.repository.EmployeeRepository; import com.example.nto.service.EmployeeService; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import java.util.Optional; +import org.springframework.transaction.annotation.Transactional; + @Service +@RequiredArgsConstructor public class EmployeeServiceImpl implements EmployeeService { - private final EmployeeRepository employeeRepository; - public EmployeeServiceImpl(EmployeeRepository employeeRepository) { - this.employeeRepository = employeeRepository; + @Override + @Transactional(readOnly = true) + public EmployeeDto getByCode(String code) { + return employeeRepository.findByCode(code).map(EmployeeDto::toDto) + .orElseThrow(() -> new EmployeeNotFoundException(("Employee with " + code + " code not found!"))); } @Override - public Optional findByCode(String code) { - return employeeRepository.findByCode(code); + @Transactional(readOnly = true) + public void auth(String code) { + if (employeeRepository.findByCode(code).isEmpty()) { + throw new EmployeeNotFoundException("Employee with " + code + " code not found!"); + } } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/nto/service/impl/PlaceServiceImpl.java b/src/main/java/com/example/nto/service/impl/PlaceServiceImpl.java deleted file mode 100644 index 3ab1cb1..0000000 --- a/src/main/java/com/example/nto/service/impl/PlaceServiceImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.example.nto.service.impl; - -import com.example.nto.entity.Place; -import com.example.nto.repository.PlaceRepository; -import com.example.nto.service.PlaceService; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class PlaceServiceImpl implements PlaceService { - - private final PlaceRepository placeRepository; - - public PlaceServiceImpl(PlaceRepository placeRepository) { - this.placeRepository = placeRepository; - } - - @Override - public List getAllPlaces() { - return placeRepository.findAll(); - } - - @Override - public Place getPlaceById(Long id) { - return placeRepository.findById(id) - .orElseThrow(() -> new RuntimeException("Place not found")); - } -}