diff --git a/src/main/java/com/example/nto/App.java b/src/main/java/com/example/nto/App.java index e453f89..d4add94 100644 --- a/src/main/java/com/example/nto/App.java +++ b/src/main/java/com/example/nto/App.java @@ -1,12 +1,11 @@ package com.example.nto; -/** - * TODO: ДОРАБОТАТЬ в рамках задания - * ================================= - * МОЖНО: Добавлять методы, аннотации, зависимости - * НЕЛЬЗЯ: Изменять название класса и пакета - */ +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication public class App { public static void main(String[] args) { + SpringApplication.run(App.class, args); } } diff --git a/src/main/java/com/example/nto/controller/BookingController.java b/src/main/java/com/example/nto/controller/BookingController.java index 9885f84..03c9937 100644 --- a/src/main/java/com/example/nto/controller/BookingController.java +++ b/src/main/java/com/example/nto/controller/BookingController.java @@ -1,10 +1,61 @@ package com.example.nto.controller; +import com.example.nto.service.BookingService; +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.Map; /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@RestController +@RequestMapping("/api/{code}") public class BookingController { + + @Autowired + private BookingService bookingService; + + @GetMapping("/booking") + public ResponseEntity getAvailablePlaces(@PathVariable String code) { + try { + if (!bookingService.employeeExists(code)) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + Map availablePlaces = bookingService.getAvailablePlaces(); + return ResponseEntity.ok(availablePlaces); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } + } + + @PostMapping("/book") + public ResponseEntity bookPlace(@PathVariable String code, @RequestBody Map request) { + try { + if (!bookingService.employeeExists(code)) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + String date = (String) request.get("date"); + Integer placeId = (Integer) request.get("placeId"); + + if (date == null || placeId == null) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } + + boolean success = bookingService.createBooking(code, date, placeId); + if (!success) { + return ResponseEntity.status(HttpStatus.CONFLICT).build(); + } + + return ResponseEntity.status(HttpStatus.CREATED).build(); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } + } } diff --git a/src/main/java/com/example/nto/controller/EmployeeController.java b/src/main/java/com/example/nto/controller/EmployeeController.java index 47658f9..ea23a53 100644 --- a/src/main/java/com/example/nto/controller/EmployeeController.java +++ b/src/main/java/com/example/nto/controller/EmployeeController.java @@ -1,10 +1,46 @@ package com.example.nto.controller; +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.*; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ + +@RestController +@RequestMapping("/api/{code}") public class EmployeeController { + + @Autowired + private EmployeeService employeeService; + + @GetMapping("/auth") + public ResponseEntity auth(@PathVariable String code) { + try { + boolean exists = employeeService.existsByCode(code); + if (!exists) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + return ResponseEntity.ok().build(); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } + } + + @GetMapping("/info") + public ResponseEntity getInfo(@PathVariable String code) { + try { + return employeeService.getEmployeeInfo(code) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); + } + } } diff --git a/src/main/java/com/example/nto/entity/Booking.java b/src/main/java/com/example/nto/entity/Booking.java index 21c1981..0a864e9 100644 --- a/src/main/java/com/example/nto/entity/Booking.java +++ b/src/main/java/com/example/nto/entity/Booking.java @@ -1,8 +1,6 @@ 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; @@ -21,8 +19,12 @@ 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; @@ -31,5 +33,7 @@ public class Booking { @JoinColumn(name = "place_id") private Place place; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "employee_id") private 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..ed04d17 100644 --- a/src/main/java/com/example/nto/entity/Employee.java +++ b/src/main/java/com/example/nto/entity/Employee.java @@ -19,14 +19,19 @@ import java.util.List; @Builder @NoArgsConstructor @AllArgsConstructor +@Entity +@Table(name = "employee") public class Employee { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String name; private String code; + @Column(name = "photo_url") private String photoUrl; @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) diff --git a/src/main/java/com/example/nto/entity/Place.java b/src/main/java/com/example/nto/entity/Place.java index 00c253b..1f2f50e 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,14 @@ 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; } diff --git a/src/main/java/com/example/nto/repository/BookingRepository.java b/src/main/java/com/example/nto/repository/BookingRepository.java index 303bb54..567f48a 100644 --- a/src/main/java/com/example/nto/repository/BookingRepository.java +++ b/src/main/java/com/example/nto/repository/BookingRepository.java @@ -1,10 +1,24 @@ package com.example.nto.repository; +import com.example.nto.entity.Booking; +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 findByDateBetween(LocalDate startDate, LocalDate endDate); + List findByEmployeeIdAndDateBetween(Long employeeId, LocalDate startDate, LocalDate endDate); + Optional findByDateAndPlaceId(LocalDate date, Long placeId); + boolean existsByEmployeeIdAndDate(Long employeeId, LocalDate date); + List findByDate(LocalDate date); } diff --git a/src/main/java/com/example/nto/repository/EmployeeRepository.java b/src/main/java/com/example/nto/repository/EmployeeRepository.java index 210d29c..570f873 100644 --- a/src/main/java/com/example/nto/repository/EmployeeRepository.java +++ b/src/main/java/com/example/nto/repository/EmployeeRepository.java @@ -1,10 +1,19 @@ package com.example.nto.repository; +import com.example.nto.entity.Employee; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ -public interface EmployeeRepository { +@Repository +public interface EmployeeRepository extends JpaRepository { + Optional findByCode(String code); + boolean existsByCode(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..aa185b4 100644 --- a/src/main/java/com/example/nto/service/BookingService.java +++ b/src/main/java/com/example/nto/service/BookingService.java @@ -1,5 +1,7 @@ package com.example.nto.service; +import java.util.Map; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= @@ -7,4 +9,7 @@ package com.example.nto.service; * НЕЛЬЗЯ: Изменять название класса и пакета */ public interface BookingService { + boolean employeeExists(String code); + Map getAvailablePlaces(); + boolean createBooking(String code, String date, Integer placeId); } diff --git a/src/main/java/com/example/nto/service/EmployeeService.java b/src/main/java/com/example/nto/service/EmployeeService.java index cccd209..b240899 100644 --- a/src/main/java/com/example/nto/service/EmployeeService.java +++ b/src/main/java/com/example/nto/service/EmployeeService.java @@ -1,5 +1,8 @@ package com.example.nto.service; +import java.util.Map; +import java.util.Optional; + /** * TODO: ДОРАБОТАТЬ в рамках задания * ================================= @@ -7,4 +10,6 @@ package com.example.nto.service; * НЕЛЬЗЯ: Изменять название класса и пакета */ public interface EmployeeService { + boolean existsByCode(String code); + Optional> getEmployeeInfo(String code); } 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..9ad3f20 100644 --- a/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java +++ b/src/main/java/com/example/nto/service/impl/BookingServiceImpl.java @@ -1,6 +1,22 @@ package com.example.nto.service.impl; import com.example.nto.service.BookingService; +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.EmployeeRepository; +import com.example.nto.repository.PlaceRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; /** * TODO: ДОРАБОТАТЬ в рамках задания @@ -8,5 +24,90 @@ import com.example.nto.service.BookingService; * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@Service public class BookingServiceImpl implements BookingService { + + @Autowired + private BookingRepository bookingRepository; + + @Autowired + private EmployeeRepository employeeRepository; + + @Autowired + private PlaceRepository placeRepository; + + @Override + public boolean employeeExists(String code) { + return employeeRepository.findByCode(code).isPresent(); + } + + @Override + public Map getAvailablePlaces() { + Map result = new HashMap<>(); + LocalDate today = LocalDate.now(); + + List allPlaces = placeRepository.findAll(); + + for (int i = 0; i < 4; i++) { + LocalDate date = today.plusDays(i); + String dateStr = date.toString(); + + List bookingsOnDate = bookingRepository.findByDate(date); + + List bookedPlaceIds = new ArrayList<>(); + for (Booking booking : bookingsOnDate) { + bookedPlaceIds.add(booking.getPlace().getId()); + } + + List> availablePlaces = new ArrayList<>(); + for (Place place : allPlaces) { + if (!bookedPlaceIds.contains(place.getId())) { + Map placeInfo = new HashMap<>(); + placeInfo.put("id", place.getId()); + placeInfo.put("place", place.getPlace()); + availablePlaces.add(placeInfo); + } + } + + result.put(dateStr, availablePlaces); + } + + return result; + } + + @Override + @Transactional + public boolean createBooking(String code, String date, Integer placeId) { + try { + Optional employeeOpt = employeeRepository.findByCode(code); + if (employeeOpt.isEmpty()) { + return false; + } + + Optional placeOpt = placeRepository.findById(placeId.longValue()); + if (placeOpt.isEmpty()) { + return false; + } + + LocalDate bookingDate = LocalDate.parse(date); + Place place = placeOpt.get(); + Employee employee = employeeOpt.get(); + + Optional existingBooking = bookingRepository.findByDateAndPlaceId(bookingDate, place.getId()); + if (existingBooking.isPresent()) { + return false; + } + + Booking booking = new Booking(); + booking.setDate(bookingDate); + booking.setPlace(place); + booking.setEmployee(employee); + + bookingRepository.save(booking); + return true; + + } catch (Exception e) { + return false; + } + } } 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..e5b581a 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,17 @@ 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.EmployeeRepository; import com.example.nto.service.EmployeeService; +import jakarta.transaction.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; /** * TODO: ДОРАБОТАТЬ в рамках задания @@ -8,5 +19,50 @@ import com.example.nto.service.EmployeeService; * МОЖНО: Добавлять методы, аннотации, зависимости * НЕЛЬЗЯ: Изменять название класса и пакета */ +@Service public class EmployeeServiceImpl implements EmployeeService { + + @Autowired + private EmployeeRepository employeeRepository; + + @Override + public boolean existsByCode(String code) { + return employeeRepository.findByCode(code).isPresent(); + } + + @Override + @Transactional + public Optional> getEmployeeInfo(String code) { + Optional employeeOpt = employeeRepository.findByCode(code); + + if (employeeOpt.isEmpty()) { + return Optional.empty(); + } + + Employee employee = employeeOpt.get(); + Map info = new HashMap<>(); + info.put("name", employee.getName()); + info.put("photoUrl", employee.getPhotoUrl()); + + Map> bookingsMap = new HashMap<>(); + + if (employee.getBookingList() != null) { + for (Booking booking : employee.getBookingList()) { + Map bookingInfo = new HashMap<>(); + bookingInfo.put("id", booking.getId()); + + Place place = booking.getPlace(); + String placeName = ""; + if (place != null) { + placeName = place.getPlace(); + } + bookingInfo.put("place", placeName); + + bookingsMap.put(booking.getDate().toString(), bookingInfo); + } + } + + info.put("booking", bookingsMap); + return Optional.of(info); + } }