student-30864-patch-1 #11
@@ -1,12 +1,11 @@
|
|||||||
package com.example.nto;
|
package com.example.nto;
|
||||||
|
|
||||||
/**
|
import org.springframework.boot.SpringApplication;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
* =================================
|
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
@SpringBootApplication
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
|
||||||
*/
|
|
||||||
public class App {
|
public class App {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(App.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,170 @@
|
|||||||
package com.example.nto.controller;
|
package com.example.nto.controller;
|
||||||
|
|
||||||
/**
|
import com.example.nto.dto.BookingRequestDto;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import com.example.nto.dto.BookingShortDto;
|
||||||
* =================================
|
import com.example.nto.dto.EmployeeInfoResponseDto;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
import com.example.nto.entity.Booking;
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
import com.example.nto.entity.Employee;
|
||||||
*/
|
import com.example.nto.entity.Place;
|
||||||
|
import com.example.nto.repository.PlaceRepository;
|
||||||
|
import com.example.nto.service.BookingService;
|
||||||
|
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.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api")
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class BookingController {
|
public class BookingController {
|
||||||
|
|
||||||
|
private final EmployeeService employeeService;
|
||||||
|
private final BookingService bookingService;
|
||||||
|
private final PlaceRepository placeRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET api/{code}/info
|
||||||
|
*
|
||||||
|
* Ответ (пример из README):
|
||||||
|
* {
|
||||||
|
* "name": "Иванов Петр Федорович",
|
||||||
|
* "photoUrl": "https://...",
|
||||||
|
* "booking": {
|
||||||
|
* "2025-01-05": {"id":1,"place":"102"},
|
||||||
|
* "2025-01-09": {"id":3,"place":"Зона 51. 50"}
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* 400 – что-то пошло не так
|
||||||
|
* 401 – кода не существует
|
||||||
|
* 200 – ОК
|
||||||
|
*/
|
||||||
|
@GetMapping("/{code}/info")
|
||||||
|
public ResponseEntity<?> getInfo(@PathVariable("code") String code) {
|
||||||
|
if (code == null || code.isBlank()) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Employee> employeeOpt = employeeService.findByCode(code);
|
||||||
|
if (employeeOpt.isEmpty()) {
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Employee employee = employeeOpt.get();
|
||||||
|
Map<LocalDate, Booking> bookings = bookingService.getBookingsByEmployee(employee);
|
||||||
|
|
||||||
|
Map<String, BookingShortDto> bookingMap = new LinkedHashMap<>();
|
||||||
|
bookings.forEach((date, booking) -> bookingMap.put(
|
||||||
|
date.toString(),
|
||||||
|
new BookingShortDto(
|
||||||
|
booking.getPlace().getId(),
|
||||||
|
booking.getPlace().getPlace()
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
EmployeeInfoResponseDto response = new EmployeeInfoResponseDto(
|
||||||
|
employee.getName(),
|
||||||
|
employee.getPhotoUrl(),
|
||||||
|
bookingMap
|
||||||
|
);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET api/{code}/booking
|
||||||
|
*
|
||||||
|
* Ответ (пример из README):
|
||||||
|
* {
|
||||||
|
* "2025-01-05": [{"id":1,"place":"102"}, {"id":2,"place":"209.13"}],
|
||||||
|
* "2025-01-06": [{"id":3,"place":"Зона 51. 50"}],
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* 400 – что-то пошло не так
|
||||||
|
* 401 – кода не существует
|
||||||
|
* 200 – ОК
|
||||||
|
*/
|
||||||
|
@GetMapping("/{code}/booking")
|
||||||
|
public ResponseEntity<?> getAvailable(@PathVariable("code") String code) {
|
||||||
|
if (code == null || code.isBlank()) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!employeeService.existsByCode(code)) {
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<LocalDate, List<Place>> available = bookingService.getAvailablePlaces();
|
||||||
|
|
||||||
|
Map<String, List<BookingShortDto>> body = new LinkedHashMap<>();
|
||||||
|
available.forEach((date, places) -> body.put(
|
||||||
|
date.toString(),
|
||||||
|
places.stream()
|
||||||
|
.map(place -> new BookingShortDto(place.getId(), place.getPlace()))
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
));
|
||||||
|
|
||||||
|
return ResponseEntity.ok(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST api/{code}/book
|
||||||
|
*
|
||||||
|
* Тело:
|
||||||
|
* {
|
||||||
|
* "date": "2025-01-05",
|
||||||
|
* "placeId": 1
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* 400 – что-то пошло не так (неправильный формат даты, нет placeId и т.п.)
|
||||||
|
* 401 – кода не существует
|
||||||
|
* 409 – место уже занято или у сотрудника уже есть бронь на эту дату
|
||||||
|
* 201 – бронирование успешно создано
|
||||||
|
*/
|
||||||
|
@PostMapping("/{code}/book")
|
||||||
|
public ResponseEntity<?> createBooking(@PathVariable("code") String code,
|
||||||
|
@RequestBody BookingRequestDto request) {
|
||||||
|
if (code == null || code.isBlank()) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Employee> employeeOpt = employeeService.findByCode(code);
|
||||||
|
if (employeeOpt.isEmpty()) {
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request == null || request.date() == null || request.placeId() == null) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDate date;
|
||||||
|
try {
|
||||||
|
date = LocalDate.parse(request.date());
|
||||||
|
} catch (DateTimeParseException ex) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Place> placeOpt = placeRepository.findById(request.placeId());
|
||||||
|
if (placeOpt.isEmpty()) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Employee employee = employeeOpt.get();
|
||||||
|
Place place = placeOpt.get();
|
||||||
|
|
||||||
|
if (bookingService.existsBookingForEmployeeOnDate(employee, date)
|
||||||
|
|| bookingService.isPlaceBookedOnDate(place, date)) {
|
||||||
|
return ResponseEntity.status(HttpStatus.CONFLICT).build(); // 409
|
||||||
|
}
|
||||||
|
|
||||||
|
bookingService.createBooking(employee, date, place);
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).build(); // 201
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,37 @@
|
|||||||
package com.example.nto.controller;
|
package com.example.nto.controller;
|
||||||
|
|
||||||
/**
|
import com.example.nto.service.EmployeeService;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import lombok.RequiredArgsConstructor;
|
||||||
* =================================
|
import org.springframework.http.HttpStatus;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
import org.springframework.http.ResponseEntity;
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
import org.springframework.web.bind.annotation.*;
|
||||||
*/
|
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api")
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class EmployeeController {
|
public class EmployeeController {
|
||||||
|
|
||||||
|
private final EmployeeService employeeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET api/{code}/auth
|
||||||
|
*
|
||||||
|
* 400 – что-то пошло не так (пустой код и т.п.)
|
||||||
|
* 401 – кода не существует
|
||||||
|
* 200 – код существует
|
||||||
|
*/
|
||||||
|
@GetMapping("/{code}/auth")
|
||||||
|
public ResponseEntity<Void> auth(@PathVariable("code") String code) {
|
||||||
|
if (code == null || code.isBlank()) {
|
||||||
|
return ResponseEntity.badRequest().build(); // 400
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean exists = employeeService.existsByCode(code);
|
||||||
|
if (!exists) {
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); // 401
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok().build(); // 200
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main/java/com/example/nto/dto/BookingRequestDto.java
Normal file
11
src/main/java/com/example/nto/dto/BookingRequestDto.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.example.nto.dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Тело запроса для POST /api/{code}/book
|
||||||
|
* {
|
||||||
|
* "date": "2025-01-05",
|
||||||
|
* "placeId": 1
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public record BookingRequestDto(String date, Long placeId) {
|
||||||
|
}
|
||||||
4
src/main/java/com/example/nto/dto/BookingShortDto.java
Normal file
4
src/main/java/com/example/nto/dto/BookingShortDto.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example.nto.dto;
|
||||||
|
|
||||||
|
public record BookingShortDto(long id, String place) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.example.nto.dto;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public record EmployeeInfoResponseDto(
|
||||||
|
String name,
|
||||||
|
String photoUrl,
|
||||||
|
Map<String, BookingShortDto> booking
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package com.example.nto.entity;
|
package com.example.nto.entity;
|
||||||
|
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.*;
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -11,25 +9,26 @@ import lombok.NoArgsConstructor;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
|
||||||
/**
|
@Entity
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
@Table(name = "booking")
|
||||||
* =================================
|
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class Booking {
|
public class Booking {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
|
@Column(name = "date")
|
||||||
private LocalDate date;
|
private LocalDate date;
|
||||||
|
|
||||||
@ManyToOne(targetEntity = Place.class, fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Place.class)
|
||||||
@JoinColumn(name = "place_id")
|
@JoinColumn(name = "place_id", nullable = false)
|
||||||
private Place place;
|
private Place place;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Employee.class)
|
||||||
|
@JoinColumn(name = "employee_id", nullable = false)
|
||||||
private Employee employee;
|
private Employee employee;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.example.nto.entity;
|
package com.example.nto.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -8,27 +9,26 @@ import lombok.NoArgsConstructor;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
/**
|
@Table(name = "employee")
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
|
||||||
* =================================
|
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class Employee {
|
public class Employee {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
|
@Column(name = "photo_url")
|
||||||
private String photoUrl;
|
private String photoUrl;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
@JsonIgnore
|
||||||
private List<Booking> bookingList;
|
private List<Booking> bookingList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,13 @@
|
|||||||
package com.example.nto.entity;
|
package com.example.nto.entity;
|
||||||
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.*;
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Entity
|
||||||
/**
|
@Table(name = "place")
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
|
||||||
* =================================
|
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
|
||||||
*/
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@@ -25,5 +18,6 @@ public class Place {
|
|||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
|
@Column(name = "place_name")
|
||||||
private String place;
|
private String place;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,26 @@
|
|||||||
package com.example.nto.repository;
|
package com.example.nto.repository;
|
||||||
|
|
||||||
/**
|
import com.example.nto.entity.Booking;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import com.example.nto.entity.Employee;
|
||||||
* =================================
|
import com.example.nto.entity.Place;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
import org.springframework.stereotype.Repository;
|
||||||
*/
|
|
||||||
public interface BookingRepository {
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface BookingRepository extends JpaRepository<Booking, Long> {
|
||||||
|
|
||||||
|
// Все брони сотрудника
|
||||||
|
List<Booking> findAllByEmployee(Employee employee);
|
||||||
|
|
||||||
|
// Все брони на дату
|
||||||
|
List<Booking> findAllByDate(LocalDate date);
|
||||||
|
|
||||||
|
// Есть ли бронь у сотрудника на эту дату
|
||||||
|
boolean existsByDateAndEmployee(LocalDate date, Employee employee);
|
||||||
|
|
||||||
|
// Занято ли место на эту дату
|
||||||
|
boolean existsByDateAndPlace(LocalDate date, Place place);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
package com.example.nto.repository;
|
package com.example.nto.repository;
|
||||||
|
|
||||||
/**
|
import com.example.nto.entity.Employee;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
* =================================
|
import org.springframework.stereotype.Repository;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
import java.util.Optional;
|
||||||
*/
|
|
||||||
public interface EmployeeRepository {
|
|
||||||
|
@Repository
|
||||||
|
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
|
||||||
|
|
||||||
|
Optional<Employee> findByCode(String code);
|
||||||
|
|
||||||
|
boolean existsByCode(String code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.example.nto.repository;
|
package com.example.nto.repository;
|
||||||
|
|
||||||
/**
|
import com.example.nto.entity.Place;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
* =================================
|
import org.springframework.stereotype.Repository;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
|
||||||
*/
|
@Repository
|
||||||
public interface PlaceRepository {
|
public interface PlaceRepository extends JpaRepository<Place, Long> {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
package com.example.nto.service;
|
package com.example.nto.service;
|
||||||
|
|
||||||
/**
|
import com.example.nto.entity.Booking;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import com.example.nto.entity.Employee;
|
||||||
* =================================
|
import com.example.nto.entity.Place;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
import java.time.LocalDate;
|
||||||
*/
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface BookingService {
|
public interface BookingService {
|
||||||
|
|
||||||
|
Map<LocalDate, Booking> getBookingsByEmployee(Employee employee);
|
||||||
|
|
||||||
|
Map<LocalDate, List<Place>> getAvailablePlaces();
|
||||||
|
|
||||||
|
boolean existsBookingForEmployeeOnDate(Employee employee, LocalDate date);
|
||||||
|
|
||||||
|
boolean isPlaceBookedOnDate(Place place, LocalDate date);
|
||||||
|
|
||||||
|
Booking createBooking(Employee employee, LocalDate date, Place place);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.example.nto.service;
|
package com.example.nto.service;
|
||||||
|
|
||||||
/**
|
import com.example.nto.entity.Employee;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
|
||||||
* =================================
|
import java.util.Optional;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
|
||||||
*/
|
|
||||||
public interface EmployeeService {
|
public interface EmployeeService {
|
||||||
|
|
||||||
|
boolean existsByCode(String code);
|
||||||
|
|
||||||
|
Optional<Employee> findByCode(String code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,85 @@
|
|||||||
package com.example.nto.service.impl;
|
package com.example.nto.service.impl;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Booking;
|
||||||
|
import com.example.nto.entity.Employee;
|
||||||
|
import com.example.nto.entity.Place;
|
||||||
|
import com.example.nto.repository.BookingRepository;
|
||||||
|
import com.example.nto.repository.PlaceRepository;
|
||||||
import com.example.nto.service.BookingService;
|
import com.example.nto.service.BookingService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
import java.time.LocalDate;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
import java.util.*;
|
||||||
* =================================
|
import java.util.stream.Collectors;
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
@Service
|
||||||
*/
|
@RequiredArgsConstructor
|
||||||
public class BookingServiceImpl implements BookingService {
|
public class BookingServiceImpl implements BookingService {
|
||||||
|
|
||||||
|
private final BookingRepository bookingRepository;
|
||||||
|
private final PlaceRepository placeRepository;
|
||||||
|
|
||||||
|
@Value("${booking.days-ahead}")
|
||||||
|
private int daysAhead;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<LocalDate, Booking> getBookingsByEmployee(Employee employee) {
|
||||||
|
List<Booking> bookings = bookingRepository.findAllByEmployee(employee);
|
||||||
|
|
||||||
|
return bookings.stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Booking::getDate,
|
||||||
|
b -> b,
|
||||||
|
(b1, b2) -> b1,
|
||||||
|
TreeMap::new
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<LocalDate, List<Place>> getAvailablePlaces() {
|
||||||
|
LocalDate start = LocalDate.now();
|
||||||
|
List<Place> allPlaces = placeRepository.findAll();
|
||||||
|
Map<LocalDate, List<Place>> result = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
for (int i = 0; i <= daysAhead; i++) {
|
||||||
|
LocalDate date = start.plusDays(i);
|
||||||
|
|
||||||
|
List<Booking> bookingsForDate = bookingRepository.findAllByDate(date);
|
||||||
|
Set<Long> busyPlaceIds = bookingsForDate.stream()
|
||||||
|
.map(b -> b.getPlace().getId())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
List<Place> available = allPlaces.stream()
|
||||||
|
.filter(p -> !busyPlaceIds.contains(p.getId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
result.put(date, available);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsBookingForEmployeeOnDate(Employee employee, LocalDate date) {
|
||||||
|
return bookingRepository.findAllByDate(date).stream()
|
||||||
|
.anyMatch(b -> b.getEmployee() != null && b.getEmployee().getId() == employee.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlaceBookedOnDate(Place place, LocalDate date) {
|
||||||
|
return bookingRepository.existsByDateAndPlace(date, place);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Booking createBooking(Employee employee, LocalDate date, Place place) {
|
||||||
|
Booking booking = Booking.builder()
|
||||||
|
.date(date)
|
||||||
|
.employee(employee)
|
||||||
|
.place(place)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return bookingRepository.save(booking);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,26 @@
|
|||||||
package com.example.nto.service.impl;
|
package com.example.nto.service.impl;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Employee;
|
||||||
|
import com.example.nto.repository.EmployeeRepository;
|
||||||
import com.example.nto.service.EmployeeService;
|
import com.example.nto.service.EmployeeService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
import java.util.Optional;
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
|
||||||
* =================================
|
@Service
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
@RequiredArgsConstructor
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
|
||||||
*/
|
|
||||||
public class EmployeeServiceImpl implements EmployeeService {
|
public class EmployeeServiceImpl implements EmployeeService {
|
||||||
|
|
||||||
|
private final EmployeeRepository employeeRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean existsByCode(String code) {
|
||||||
|
return employeeRepository.existsByCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Employee> findByCode(String code) {
|
||||||
|
return employeeRepository.findByCode(code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user