main #10
@@ -1,12 +1,17 @@
|
|||||||
package com.example.nto;
|
package com.example.nto;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
|
@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,83 @@
|
|||||||
package com.example.nto.controller;
|
package com.example.nto.controller;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Booking;
|
||||||
|
import com.example.nto.exception.BookingConflictException;
|
||||||
|
import com.example.nto.exception.EmployeeNotFoundException;
|
||||||
|
import com.example.nto.exception.InvalidBookingException;
|
||||||
|
import com.example.nto.service.BookingService;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.ErrorResponse;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api")
|
||||||
public class BookingController {
|
public class BookingController {
|
||||||
|
|
||||||
|
private final BookingService bookingService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public BookingController(BookingService bookingService) {
|
||||||
|
this.bookingService = bookingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{code}/booking")
|
||||||
|
public ResponseEntity<Map<String, List<Booking.AvailablePlaceDto>>> getAvailablePlaces(
|
||||||
|
@PathVariable String code
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (!bookingService.isEmployeeExists(code)) {
|
||||||
|
return ResponseEntity
|
||||||
|
.status(401).build();
|
||||||
|
}
|
||||||
|
Map<String, List<Booking.AvailablePlaceDto>> response = bookingService.getAvailablePlaces(code);
|
||||||
|
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@PostMapping("/{code}/book")
|
||||||
|
public ResponseEntity<?> createBooking(
|
||||||
|
@PathVariable String code,
|
||||||
|
@RequestBody Booking.CreateBookingRequest request
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
Booking booking = bookingService.createBooking(code, request.getDate(), request.getPlaceId());
|
||||||
|
System.out.println("OK");
|
||||||
|
return ResponseEntity.status(HttpStatus.CREATED).build();
|
||||||
|
|
||||||
|
} catch (EmployeeNotFoundException e) {
|
||||||
|
System.out.println("NOT");
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
} catch (BookingConflictException e) {
|
||||||
|
System.out.println("NOT1");
|
||||||
|
return ResponseEntity.status(HttpStatus.CONFLICT).build();
|
||||||
|
} catch (InvalidBookingException e) {
|
||||||
|
System.out.println("NOT2");
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("NOT3");
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,52 @@
|
|||||||
package com.example.nto.controller;
|
package com.example.nto.controller;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Employee;
|
||||||
|
import com.example.nto.repository.EmployeeRepository;
|
||||||
|
import com.example.nto.service.EmployeeService;
|
||||||
|
import com.example.nto.service.impl.EmployeeServiceImpl;
|
||||||
|
import org.hibernate.resource.beans.container.spi.BeanLifecycleStrategy;
|
||||||
|
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.net.http.HttpResponse;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("api")
|
||||||
public class EmployeeController {
|
public class EmployeeController {
|
||||||
|
|
||||||
|
private final EmployeeService employeeService;
|
||||||
|
|
||||||
|
public EmployeeController(EmployeeService employeeService) {
|
||||||
|
|
||||||
|
this.employeeService = employeeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{code}/auth")
|
||||||
|
public ResponseEntity<?> Isauth(@PathVariable String code) {
|
||||||
|
if (employeeService.isCodeValid(code)) {
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
|
||||||
|
} else if (!employeeService.isCodeValid(code)){
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{code}/info")
|
||||||
|
public ResponseEntity<Map<String, Object>> getEmployeeInfo(@PathVariable String code) {
|
||||||
|
Map<String, Object> response = employeeService.getEmployeeInfo(code);
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package com.example.nto.entity;
|
package com.example.nto.entity;
|
||||||
|
|
||||||
import jakarta.persistence.FetchType;
|
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||||
import jakarta.persistence.JoinColumn;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import jakarta.persistence.ManyToOne;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import jakarta.persistence.*;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -21,8 +22,10 @@ import java.time.LocalDate;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@Entity
|
||||||
public class Booking {
|
public class Booking {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
private LocalDate date;
|
private LocalDate date;
|
||||||
@@ -31,5 +34,43 @@ public class Booking {
|
|||||||
@JoinColumn(name = "place_id")
|
@JoinColumn(name = "place_id")
|
||||||
private Place place;
|
private Place place;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "employee_id")
|
||||||
|
@JsonBackReference
|
||||||
private Employee employee;
|
private Employee employee;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class AvailablePlaceDto {
|
||||||
|
private long id;
|
||||||
|
private String place;
|
||||||
|
}
|
||||||
|
@Data
|
||||||
|
public static class CreateBookingRequest {
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private LocalDate date;
|
||||||
|
private long placeId;
|
||||||
|
}
|
||||||
|
@Data
|
||||||
|
public static class ErrorResponse {
|
||||||
|
private String error;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public ErrorResponse(String error, String message) {
|
||||||
|
this.error = error;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class BookingResponse {
|
||||||
|
private Long id;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private LocalDate date;
|
||||||
|
private Long placeId;
|
||||||
|
private String placeName;
|
||||||
|
private Long employeeId;
|
||||||
|
private String employeeName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.example.nto.entity;
|
package com.example.nto.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonManagedReference;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -19,8 +21,12 @@ import java.util.List;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@Entity
|
||||||
|
@JsonSerialize
|
||||||
public class Employee {
|
public class Employee {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
@@ -29,6 +35,16 @@ public class Employee {
|
|||||||
|
|
||||||
private String photoUrl;
|
private String photoUrl;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY,
|
||||||
|
targetEntity = Booking.class)
|
||||||
|
@JsonManagedReference
|
||||||
private List<Booking> bookingList;
|
private List<Booking> bookingList;
|
||||||
|
|
||||||
|
public Employee(long id, String name, String code, String photoUrl) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.code = code;
|
||||||
|
this.photoUrl = photoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
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;
|
||||||
@@ -18,12 +16,19 @@ import lombok.NoArgsConstructor;
|
|||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@Entity
|
||||||
public class Place {
|
public class Place {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@Column(name = "id")
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
|
|
||||||
|
@Column(name = "place_name")
|
||||||
private String place;
|
private String place;
|
||||||
|
|
||||||
|
public Place(long id, String place){
|
||||||
|
this.id = id;
|
||||||
|
this.place = place;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.example.nto.exception;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.CONFLICT)
|
||||||
|
public class BookingConflictException extends RuntimeException {
|
||||||
|
public BookingConflictException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.example.nto.exception;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||||
|
public class EmployeeNotFoundException extends RuntimeException {
|
||||||
|
public EmployeeNotFoundException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.example.nto.exception;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
public class InvalidBookingException extends RuntimeException {
|
||||||
|
public InvalidBookingException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,29 @@
|
|||||||
package com.example.nto.repository;
|
package com.example.nto.repository;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Booking;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
public interface BookingRepository {
|
@Service
|
||||||
|
@Repository
|
||||||
|
public interface BookingRepository extends JpaRepository<Booking, Long> {
|
||||||
|
List<Booking> findByDateIn(List<LocalDate> dates);
|
||||||
|
|
||||||
|
Optional<Booking> findById(Long id);
|
||||||
|
|
||||||
|
List<Booking> findByDateInAndEmployee_Code(List<LocalDate> dates, String employeeCode);
|
||||||
|
Optional<Booking> findByDateAndPlace_Id(LocalDate date, long placeId);
|
||||||
|
List<Booking> findByDateAndEmployee_Code(LocalDate date, String employeeCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
package com.example.nto.repository;
|
package com.example.nto.repository;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Employee;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
public interface EmployeeRepository {
|
|
||||||
|
@Service
|
||||||
|
@Repository
|
||||||
|
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
|
||||||
|
Optional<Employee> findByCode(String code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
package com.example.nto.repository;
|
package com.example.nto.repository;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Booking;
|
||||||
|
import com.example.nto.entity.Place;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
public interface PlaceRepository {
|
public interface PlaceRepository extends JpaRepository<Place, Long> {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
package com.example.nto.service;
|
package com.example.nto.service;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Booking;
|
||||||
|
import com.example.nto.entity.Employee;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
@@ -7,4 +15,12 @@ package com.example.nto.service;
|
|||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
public interface BookingService {
|
public interface BookingService {
|
||||||
|
List<Booking> getAll();
|
||||||
|
Optional<Booking> getBookingById(Long id);
|
||||||
|
|
||||||
|
Map<String, List<Booking.AvailablePlaceDto>> getAvailablePlaces(String code);
|
||||||
|
|
||||||
|
boolean isEmployeeExists(String code);
|
||||||
|
Booking createBooking(String employeeCode, LocalDate date, long placeId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package com.example.nto.service;
|
package com.example.nto.service;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Employee;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
* =================================
|
* =================================
|
||||||
@@ -7,4 +13,12 @@ package com.example.nto.service;
|
|||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
public interface EmployeeService {
|
public interface EmployeeService {
|
||||||
|
List<Employee> getAll();
|
||||||
|
|
||||||
|
Optional<Employee> getByCode(String code);
|
||||||
|
|
||||||
|
|
||||||
|
boolean isCodeValid(String code);
|
||||||
|
|
||||||
|
Map<String, Object> getEmployeeInfo(String code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,24 @@
|
|||||||
package com.example.nto.service.impl;
|
package com.example.nto.service.impl;
|
||||||
|
|
||||||
|
import com.example.nto.entity.Booking;
|
||||||
|
import com.example.nto.entity.Booking.AvailablePlaceDto;
|
||||||
|
import com.example.nto.entity.Employee;
|
||||||
|
import com.example.nto.entity.Place;
|
||||||
|
import com.example.nto.exception.BookingConflictException;
|
||||||
|
import com.example.nto.exception.EmployeeNotFoundException;
|
||||||
|
import com.example.nto.exception.InvalidBookingException;
|
||||||
|
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.BookingService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
@@ -8,5 +26,123 @@ import com.example.nto.service.BookingService;
|
|||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
|
@Component
|
||||||
|
@Service
|
||||||
public class BookingServiceImpl implements BookingService {
|
public class BookingServiceImpl implements BookingService {
|
||||||
|
|
||||||
|
private final BookingRepository bookingRepository;
|
||||||
|
private final PlaceRepository placeRepository;
|
||||||
|
private final EmployeeRepository employeeRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Booking> getAll() {
|
||||||
|
return bookingRepository.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Booking> getBookingById(Long id) {
|
||||||
|
return bookingRepository.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public BookingServiceImpl(BookingRepository bookingRepository, PlaceRepository placeRepository,
|
||||||
|
EmployeeRepository employeeRepository) {
|
||||||
|
this.bookingRepository = bookingRepository;
|
||||||
|
this.placeRepository = placeRepository;
|
||||||
|
this.employeeRepository = employeeRepository;
|
||||||
|
}
|
||||||
|
public boolean isEmployeeExists(String code) {
|
||||||
|
return employeeRepository.findByCode(code).isPresent();
|
||||||
|
}
|
||||||
|
public Map<String, List<AvailablePlaceDto>> getAvailablePlaces(String employeeCode) {
|
||||||
|
Employee employee = employeeRepository.findByCode(employeeCode)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Employee not found"));
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
List<LocalDate> targetDates = List.of(
|
||||||
|
today,
|
||||||
|
today.plusDays(1),
|
||||||
|
today.plusDays(2),
|
||||||
|
today.plusDays(3)
|
||||||
|
);
|
||||||
|
List<Place> allPlaces = placeRepository.findAll();
|
||||||
|
List<Booking> bookings = bookingRepository.findByDateIn(targetDates);
|
||||||
|
Map<LocalDate, List<Booking>> bookingsByDate = bookings.stream()
|
||||||
|
.collect(Collectors.groupingBy(Booking::getDate));
|
||||||
|
Map<String, List<AvailablePlaceDto>> result = new HashMap<>();
|
||||||
|
for (LocalDate date : targetDates) {
|
||||||
|
String dateKey = date.toString(); // Формат: "yyyy-MM-dd"
|
||||||
|
List<Booking> dayBookings = bookingsByDate.getOrDefault(date, List.of());
|
||||||
|
Set<Long> occupiedPlaceIds = dayBookings.stream()
|
||||||
|
.map(booking -> booking.getPlace().getId())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
List<AvailablePlaceDto> available = allPlaces.stream()
|
||||||
|
.filter(place -> !occupiedPlaceIds.contains(place.getId()))
|
||||||
|
.map(place -> {
|
||||||
|
AvailablePlaceDto dto = new AvailablePlaceDto();
|
||||||
|
dto.setId(place.getId());
|
||||||
|
dto.setPlace(place.getPlace());
|
||||||
|
return dto;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
result.put(dateKey, available);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public Booking createBooking(String employeeCode, LocalDate date, long placeId) {
|
||||||
|
Employee employee = employeeRepository.findByCode(employeeCode)
|
||||||
|
.orElseThrow(() -> new EmployeeNotFoundException("Employee with code '" + employeeCode + "' not found"));
|
||||||
|
Place place = placeRepository.findById(placeId)
|
||||||
|
.orElseThrow(() -> new InvalidBookingException("Place with id " + placeId + " not found"));
|
||||||
|
validateBookingDate(date);
|
||||||
|
checkPlaceAvailability(date, placeId);
|
||||||
|
checkEmployeeBookingConflict(employeeCode, date);
|
||||||
|
Booking booking = Booking.builder()
|
||||||
|
.date(date)
|
||||||
|
.place(place)
|
||||||
|
.employee(employee)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return bookingRepository.save(booking);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateBookingDate(LocalDate date) {
|
||||||
|
LocalDate today = LocalDate.now();
|
||||||
|
LocalDate maxDate = today.plusDays(3);
|
||||||
|
|
||||||
|
if (date == null) {
|
||||||
|
throw new InvalidBookingException("Date is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (date.isBefore(today)) {
|
||||||
|
throw new InvalidBookingException("Cannot book in the past");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (date.isAfter(maxDate)) {
|
||||||
|
throw new InvalidBookingException("Can only book up to 3 days in advance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPlaceAvailability(LocalDate date, long placeId) {
|
||||||
|
Optional<Booking> existingBooking = bookingRepository.findByDateAndPlace_Id(date, placeId);
|
||||||
|
if (existingBooking.isPresent()) {
|
||||||
|
throw new BookingConflictException("Place " + placeId + " is already booked for " + date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkEmployeeBookingConflict(String employeeCode, LocalDate date) {
|
||||||
|
List<Booking> employeeBookingsOnDate = bookingRepository.findByDateAndEmployee_Code(date, employeeCode);
|
||||||
|
if (!employeeBookingsOnDate.isEmpty()) {
|
||||||
|
throw new BookingConflictException("Employee already has a booking on " + date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
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.repository.EmployeeRepository;
|
||||||
import com.example.nto.service.EmployeeService;
|
import com.example.nto.service.EmployeeService;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: ДОРАБОТАТЬ в рамках задания
|
* TODO: ДОРАБОТАТЬ в рамках задания
|
||||||
@@ -8,5 +22,51 @@ import com.example.nto.service.EmployeeService;
|
|||||||
* МОЖНО: Добавлять методы, аннотации, зависимости
|
* МОЖНО: Добавлять методы, аннотации, зависимости
|
||||||
* НЕЛЬЗЯ: Изменять название класса и пакета
|
* НЕЛЬЗЯ: Изменять название класса и пакета
|
||||||
*/
|
*/
|
||||||
|
@Component
|
||||||
|
@Service
|
||||||
public class EmployeeServiceImpl implements EmployeeService {
|
public class EmployeeServiceImpl implements EmployeeService {
|
||||||
|
private final EmployeeRepository employeeRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public EmployeeServiceImpl(EmployeeRepository employeeRepository) {
|
||||||
|
this.employeeRepository = employeeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Employee> getAll() {
|
||||||
|
return employeeRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Employee> getByCode(String code) {
|
||||||
|
return employeeRepository.findByCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCodeValid(String code){
|
||||||
|
return employeeRepository.findByCode(code).isPresent();
|
||||||
|
}
|
||||||
|
public Map<String, Object> getEmployeeInfo(String code) {
|
||||||
|
Employee employee = getByCode(code)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Employee not found"));
|
||||||
|
|
||||||
|
Map<LocalDate, Map<String, Object>> bookingMap = employee.getBookingList().stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Booking::getDate,
|
||||||
|
booking -> {
|
||||||
|
Map<String, Object> info = new HashMap<>();
|
||||||
|
info.put("id", booking.getId());
|
||||||
|
info.put("place", booking.getPlace().getPlace());
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("name", employee.getName());
|
||||||
|
result.put("photoUrl", employee.getPhotoUrl());
|
||||||
|
result.put("booking", bookingMap);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user