diff --git a/src/main/java/com/example/nto/App.java b/src/main/java/com/example/nto/App.java index e453f89..65401fc 100644 --- a/src/main/java/com/example/nto/App.java +++ b/src/main/java/com/example/nto/App.java @@ -1,4 +1,8 @@ package com.example.nto; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; /** * TODO: ДОРАБОТАТЬ в рамках задания @@ -6,7 +10,16 @@ package com.example.nto; * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@SpringBootApplication public class App { public static void main(String[] args) { + SpringApplication.run(App.class , args); + } + @RestController + public static class HomeController { + @GetMapping("/") + public String home() { + return "Сервер работает!"; + } } } diff --git a/src/main/java/com/example/nto/controller/BookingController.java b/src/main/java/com/example/nto/controller/BookingController.java index 9885f84..562837d 100644 --- a/src/main/java/com/example/nto/controller/BookingController.java +++ b/src/main/java/com/example/nto/controller/BookingController.java @@ -1,10 +1,121 @@ 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.excepation.EmployeeNotFoundException; +import com.example.nto.repository.BookingRepository; +import com.example.nto.repository.PlaceRepository; +import com.example.nto.service.BookingService; +import com.example.nto.service.EmployeeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@RestController +@RequestMapping("/api") public class BookingController { + @Autowired + private BookingService bookingService; + @Autowired + private PlaceRepository placeRepository; + @Autowired + private BookingRepository bookingRepository; + @Autowired + private EmployeeService employeeService; + + @GetMapping("/{code}/booking") + public ResponseEntity getAvailableBookings(@PathVariable String code) { + try { + Map response = bookingService.findAvailableBookings(code); + return ResponseEntity.ok(response); + } catch (IllegalArgumentException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage()); + } catch (EmployeeNotFoundException e) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage()); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Unexpected error"); + } + } + + @PostMapping("/{code}/book") + public ResponseEntity createBooking( + @PathVariable String code, + @RequestParam Long placeId, + @RequestParam String date + ) { + try { + // Проверка обязательных параметров + if (placeId == null || date == null || date.isEmpty()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body("Place ID and date must be provided"); + } + Employee employee = employeeService.getEmployeeWithBookings(code); + if (employee == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body("Employee not found"); + } + + // Получаем место + Place place = placeRepository.findById(placeId).orElse(null); + if (place == null) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body("Place not found"); + } + + // Парсим дату + LocalDate bookingDate; + try { + bookingDate = LocalDate.parse(date); + } catch (Exception ex) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body("Invalid date format. Use yyyy-MM-dd"); + } + + // Проверяем, свободно ли место на эту дату + boolean exists = bookingRepository.findByDateBetween(bookingDate, bookingDate) + .stream() + .anyMatch(b -> b.getPlace().getId() == placeId); + if (exists) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body("Place already booked for this date"); + } + Booking booking = new Booking(); + booking.setEmployee((Map) employee); + booking.setPlace(place); + booking.setDate(bookingDate); + bookingRepository.save(booking); + + // Формируем ответ + Map response = new LinkedHashMap<>(); + response.put("id", booking.getId()); + response.put("date", booking.getDate()); + response.put("placeId", place.getId()); + response.put("employeeId", employee.getId()); + + return ResponseEntity.status(HttpStatus.CREATED).body(response); + + } catch (java.lang.IllegalArgumentException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage()); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Unexpected error"); + } + } } + + + + diff --git a/src/main/java/com/example/nto/controller/EmployeeController.java b/src/main/java/com/example/nto/controller/EmployeeController.java index 47658f9..e218396 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -1,10 +1,58 @@ package com.example.nto.controller; +import com.example.nto.entity.Booking; +import com.example.nto.entity.Employee; +import com.example.nto.excepation.EmployeeNotFoundException; +import com.example.nto.repository.BookingRepository; +import com.example.nto.repository.EmployeeRepository; +import com.example.nto.service.EmployeeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@RestController +@RequestMapping("/api") public class EmployeeController { -} + + @Autowired + private EmployeeService employeeService; + @GetMapping("/{code}/auth") + public ResponseEntity checkAuth( + @PathVariable String code, + @RequestHeader(value = "Authorization", required = false) String authHeader) { + if (authHeader == null || !authHeader.equals("Bearer valid-token")) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + try { + employeeService. getEmployeeWithBookings(code); + return ResponseEntity.ok().build(); + } catch (IllegalArgumentException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } catch (EmployeeNotFoundException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + } + + @GetMapping("/{code}/info") + public ResponseEntity getEmployeeInfo(@PathVariable String code) { + try { + Employee response = employeeService.getEmployeeWithBookings(code); + return ResponseEntity.ok(response); + } catch (IllegalArgumentException e) { + return ResponseEntity.status(400).body(e.getMessage()); + } catch (EmployeeNotFoundException e) { + return ResponseEntity.status(404).body(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/example/nto/controller/EmployeeFullInfoResponseDto.java b/src/main/java/com/example/nto/controller/EmployeeFullInfoResponseDto.java new file mode 100644 index 0000000..5cf8c08 --- /dev/null +++ b/src/main/java/com/example/nto/controller/EmployeeFullInfoResponseDto.java @@ -0,0 +1,27 @@ +package com.example.nto.controller; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Map; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class EmployeeFullInfoResponseDto { + private String name; + private String photoUrl; + private Map booking; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class BookingInfo { + private Long id; + private String place; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/nto/entity/Booking.java b/src/main/java/com/example/nto/entity/Booking.java index 21c1981..c7b37eb 100644 --- a/src/main/java/com/example/nto/entity/Booking.java +++ b/src/main/java/com/example/nto/entity/Booking.java @@ -1,14 +1,13 @@ package com.example.nto.entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDate; +import java.util.Map; /** @@ -21,15 +20,45 @@ import java.time.LocalDate; @Builder @NoArgsConstructor @AllArgsConstructor +@Entity +@Table(name="booking") public class Booking { - + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; - private LocalDate date; - @ManyToOne(targetEntity = Place.class, fetch = FetchType.LAZY) @JoinColumn(name = "place_id") private Place place; - + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "employee_id") private Employee employee; + + + public Place getPlace() { + return place; + } + public LocalDate getDate() { + return date; + } + + public Object getId() { + return id; + } + + public Employee getEmployee() { + return employee; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public void setPlace(Place place) { + this.place = place; + } + + public void setEmployee(Map employee) { + this.employee = (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 a52102b..14249f0 100644 --- a/src/main/java/com/example/nto/entity/Employee.java +++ b/src/main/java/com/example/nto/entity/Employee.java @@ -1,11 +1,11 @@ package com.example.nto.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; - import java.util.List; @@ -19,10 +19,13 @@ import java.util.List; @Builder @NoArgsConstructor @AllArgsConstructor +@Entity +@Table(name="employee") public class Employee { - + @Id private long id; + private String name; private String code; @@ -30,5 +33,26 @@ public class Employee { private String photoUrl; @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JsonIgnore private List bookingList; + + public List getBookingList() { + return bookingList; + } + + public Object getCode() { + return code; + } + + public Object getPhotoUrl() { + return photoUrl; + } + + public Object getName() { + return name; + } + + public Object getId() { + return id; + } } diff --git a/src/main/java/com/example/nto/entity/Place.java b/src/main/java/com/example/nto/entity/Place.java index 00c253b..32947c7 100644 --- a/src/main/java/com/example/nto/entity/Place.java +++ b/src/main/java/com/example/nto/entity/Place.java @@ -1,8 +1,6 @@ package com.example.nto.entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -19,11 +17,26 @@ import lombok.NoArgsConstructor; @Builder @NoArgsConstructor @AllArgsConstructor +@Entity +@Table(name="place") public class Place { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; - + @Column(name = "place_name") private String place; + + public Place(int id, String place) { + } + + + public Object getPlace() { + return place; + } + + public Long getId() { + return id; + } } + + + diff --git a/src/main/java/com/example/nto/excepation/ConflictException.java b/src/main/java/com/example/nto/excepation/ConflictException.java new file mode 100644 index 0000000..2c6ad3b --- /dev/null +++ b/src/main/java/com/example/nto/excepation/ConflictException.java @@ -0,0 +1,7 @@ +package com.example.nto.excepation; + +public class ConflictException extends RuntimeException { + public ConflictException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/excepation/EmployeeNotFoundException.java b/src/main/java/com/example/nto/excepation/EmployeeNotFoundException.java new file mode 100644 index 0000000..c59e73a --- /dev/null +++ b/src/main/java/com/example/nto/excepation/EmployeeNotFoundException.java @@ -0,0 +1,7 @@ +package com.example.nto.excepation; + +public class EmployeeNotFoundException extends RuntimeException{ + public EmployeeNotFoundException(String msg) { + super(msg); + } +} diff --git a/src/main/java/com/example/nto/excepation/IllegalArgumentException.java b/src/main/java/com/example/nto/excepation/IllegalArgumentException.java new file mode 100644 index 0000000..00cc715 --- /dev/null +++ b/src/main/java/com/example/nto/excepation/IllegalArgumentException.java @@ -0,0 +1,7 @@ +package com.example.nto.excepation; + +public class IllegalArgumentException extends RuntimeException { + public IllegalArgumentException(String message) { + super(message); + } +} diff --git a/src/main/java/com/example/nto/repository/BookingRepository.java b/src/main/java/com/example/nto/repository/BookingRepository.java index 303bb54..f2876d4 100644 --- a/src/main/java/com/example/nto/repository/BookingRepository.java +++ b/src/main/java/com/example/nto/repository/BookingRepository.java @@ -1,10 +1,23 @@ package com.example.nto.repository; +import com.example.nto.entity.Booking; +import com.example.nto.entity.Employee; +import com.example.nto.entity.Place; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ -public interface BookingRepository { +@Repository +public interface BookingRepository extends JpaRepository { + List findByEmployee(Employee employee); + List findByDateBetween(LocalDate start, LocalDate end); } diff --git a/src/main/java/com/example/nto/repository/EmployeeRepository.java b/src/main/java/com/example/nto/repository/EmployeeRepository.java index 210d29c..b0e5b28 100644 --- a/src/main/java/com/example/nto/repository/EmployeeRepository.java +++ b/src/main/java/com/example/nto/repository/EmployeeRepository.java @@ -1,10 +1,16 @@ package com.example.nto.repository; +import com.example.nto.entity.Employee; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ -public interface EmployeeRepository { +@Repository +public interface EmployeeRepository extends JpaRepository { + Employee findByCode(String code); } diff --git a/src/main/java/com/example/nto/repository/PlaceRepository.java b/src/main/java/com/example/nto/repository/PlaceRepository.java index d3bea1d..425dacb 100644 --- a/src/main/java/com/example/nto/repository/PlaceRepository.java +++ b/src/main/java/com/example/nto/repository/PlaceRepository.java @@ -1,10 +1,15 @@ package com.example.nto.repository; +import com.example.nto.entity.Place; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ -public interface PlaceRepository { +@Repository +public interface PlaceRepository extends JpaRepository { } diff --git a/src/main/java/com/example/nto/service/BookingService.java b/src/main/java/com/example/nto/service/BookingService.java index 31ec148..6629e95 100644 --- a/src/main/java/com/example/nto/service/BookingService.java +++ b/src/main/java/com/example/nto/service/BookingService.java @@ -1,10 +1,11 @@ package com.example.nto.service; -/** - * TODO: ДОРАБОТАТЬ в рамках задания - * ================================= - * МОЖНО: Добавлять методы, аннотации, зависимости - * НЕЛЬЗЯ: Изменять название класса и пакета - */ +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +@Service public interface BookingService { + Map findAvailableBookings(String employeeCode); } diff --git a/src/main/java/com/example/nto/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java index cccd209..35f7b21 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -1,4 +1,10 @@ package com.example.nto.service; +import com.example.nto.entity.Booking; +import com.example.nto.entity.Employee; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; /** * TODO: ДОРАБОТАТЬ в рамках задания @@ -6,5 +12,7 @@ package com.example.nto.service; * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@Service public interface EmployeeService { + Employee getEmployeeWithBookings(String code); } diff --git a/src/main/java/com/example/nto/service/PlaceServise.java b/src/main/java/com/example/nto/service/PlaceServise.java new file mode 100644 index 0000000..4ee1351 --- /dev/null +++ b/src/main/java/com/example/nto/service/PlaceServise.java @@ -0,0 +1,25 @@ +package com.example.nto.service; +import com.example.nto.entity.Place; +import com.example.nto.repository.PlaceRepository; +import jakarta.annotation.PostConstruct; +import org.springframework.stereotype.Service; + +@Service +public class PlaceServise { + private final PlaceRepository placeRepository; + + public PlaceServise(PlaceRepository placeRepository) { + this.placeRepository = placeRepository; + } + + @PostConstruct + public void Places() { + if(placeRepository.count() == 0) { + placeRepository.save(new Place(1,"K-19")); + placeRepository.save(new Place(2,"M-16")); + placeRepository.save(new Place(3,"T-1")); + } + } + +} + 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 d24b244..341abcf 100644 --- a/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java @@ -1,12 +1,64 @@ 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.excepation.EmployeeNotFoundException; +import com.example.nto.repository.BookingRepository; +import com.example.nto.repository.PlaceRepository; import com.example.nto.service.BookingService; +import com.example.nto.service.EmployeeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; -/** - * TODO: ДОРАБОТАТЬ в рамках задания - * ================================= - * МОЖНО: Добавлять методы, аннотации, зависимости - * НЕЛЬЗЯ: Изменять название класса и пакета - */ +import java.time.LocalDate; +import java.util.*; + +@Service public class BookingServiceImpl implements BookingService { + + @Autowired + private BookingRepository bookingRepository; + + @Autowired + private PlaceRepository placeRepository; + + @Autowired + private EmployeeService employeeService; + + @Override + public Map findAvailableBookings(String employeeCode) { + if (employeeCode == null || employeeCode.isEmpty()) { + throw new IllegalArgumentException("Employee code cannot be null or empty"); + } + Employee employee = employeeService.getEmployeeWithBookings(employeeCode); + if (employee == null) { + throw new EmployeeNotFoundException("Employee not found with code: " + employeeCode); + } + + LocalDate today = LocalDate.now(); + LocalDate endDate = today.plusDays(3); + List bookings = bookingRepository.findByDateBetween(today, endDate); + List places = placeRepository.findAll(); + Map>> result = new LinkedHashMap<>(); + for (int i = 0; i <= 3; i++) { + LocalDate date = today.plusDays(i); + List> freePlaces = new ArrayList<>(); + for (Place place : places) { + boolean isBooked = bookings.stream() + .anyMatch(b -> b.getDate().isEqual(date) && b.getPlace().getId() == place.getId()); + if (!isBooked) { + Map placeInfo = new LinkedHashMap<>(); + placeInfo.put("id", place.getId()); + placeInfo.put("place", place.getPlace()); + freePlaces.add(placeInfo); + } + } + result.put(date.toString(), freePlaces); + } + return Collections.unmodifiableMap(result); + } } + + + 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 f8125e5..8b330fc 100644 --- a/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/EmployeeServiceImpl.java @@ -1,6 +1,15 @@ package com.example.nto.service.impl; - +import com.example.nto.entity.Booking; +import com.example.nto.entity.Employee; +import com.example.nto.excepation.EmployeeNotFoundException; +import com.example.nto.repository.BookingRepository; +import com.example.nto.repository.EmployeeRepository; import com.example.nto.service.EmployeeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + /** * TODO: ДОРАБОТАТЬ в рамках задания @@ -8,5 +17,25 @@ import com.example.nto.service.EmployeeService; * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@Service public class EmployeeServiceImpl implements EmployeeService { -} + + @Autowired + private EmployeeRepository employeeRepository; + + @Autowired + private BookingRepository bookingRepository; + + @Override + public Employee getEmployeeWithBookings(String code) { + if (code == null || code.isEmpty()) { + throw new IllegalArgumentException("Employee code cannot be null or empty"); + } + Employee employee = employeeRepository.findByCode(code); + if (employee == null) { + throw new EmployeeNotFoundException("Employee not found with code: " + code); + } + return employee; + } + +} \ No newline at end of file