diff --git a/src/main/java/ac/knu/likeknu/controller/AnnouncementController.java b/src/main/java/ac/knu/likeknu/controller/AnnouncementController.java index 45b9851..d2c76ea 100644 --- a/src/main/java/ac/knu/likeknu/controller/AnnouncementController.java +++ b/src/main/java/ac/knu/likeknu/controller/AnnouncementController.java @@ -3,8 +3,8 @@ import ac.knu.likeknu.controller.dto.announcement.AnnouncementListResponse; import ac.knu.likeknu.controller.dto.base.PageDto; import ac.knu.likeknu.controller.dto.base.PageResponseDto; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Category; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Category; import ac.knu.likeknu.logging.domain.value.LogType; import ac.knu.likeknu.logging.service.LoggingService; import ac.knu.likeknu.service.AnnouncementService; diff --git a/src/main/java/ac/knu/likeknu/controller/BusController.java b/src/main/java/ac/knu/likeknu/controller/BusController.java index 176fcec..ed049a0 100644 --- a/src/main/java/ac/knu/likeknu/controller/BusController.java +++ b/src/main/java/ac/knu/likeknu/controller/BusController.java @@ -4,8 +4,8 @@ import ac.knu.likeknu.controller.dto.citybus.CityBusesResponse; import ac.knu.likeknu.controller.dto.shuttlebus.ShuttleBusesArrivalTimeResponse; import ac.knu.likeknu.controller.dto.shuttlebus.ShuttleListResponse; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.RouteType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.RouteType; import ac.knu.likeknu.logging.domain.value.LogType; import ac.knu.likeknu.logging.service.LoggingService; import ac.knu.likeknu.service.CityBusService; diff --git a/src/main/java/ac/knu/likeknu/controller/MainController.java b/src/main/java/ac/knu/likeknu/controller/MainController.java index 6f8fcfe..43c8223 100644 --- a/src/main/java/ac/knu/likeknu/controller/MainController.java +++ b/src/main/java/ac/knu/likeknu/controller/MainController.java @@ -1,12 +1,12 @@ package ac.knu.likeknu.controller; import ac.knu.likeknu.controller.dto.base.ResponseDto; -import ac.knu.likeknu.controller.dto.main.MainAnnouncementsResponse; -import ac.knu.likeknu.controller.dto.main.MainCityBusResponse; -import ac.knu.likeknu.controller.dto.main.MainMenuResponse; -import ac.knu.likeknu.controller.dto.main.MainScheduleResponse; +import ac.knu.likeknu.controller.dto.announcement.MainAnnouncementsResponse; +import ac.knu.likeknu.controller.dto.citybus.MainCityBusResponse; +import ac.knu.likeknu.controller.dto.menu.MainMenuResponse; +import ac.knu.likeknu.controller.dto.schedule.MainScheduleResponse; import ac.knu.likeknu.domain.MainHeaderMessage; -import ac.knu.likeknu.domain.value.Campus; +import ac.knu.likeknu.domain.constants.Campus; import ac.knu.likeknu.exception.BusinessException; import ac.knu.likeknu.repository.MainHeaderMessageRepository; import ac.knu.likeknu.service.CityBusService; diff --git a/src/main/java/ac/knu/likeknu/controller/MenuController.java b/src/main/java/ac/knu/likeknu/controller/MenuController.java index 022d747..1b68980 100644 --- a/src/main/java/ac/knu/likeknu/controller/MenuController.java +++ b/src/main/java/ac/knu/likeknu/controller/MenuController.java @@ -1,36 +1,61 @@ package ac.knu.likeknu.controller; import ac.knu.likeknu.controller.dto.base.ResponseDto; -import ac.knu.likeknu.controller.dto.menu.MenuResponse; -import ac.knu.likeknu.domain.value.Campus; +import ac.knu.likeknu.controller.dto.menu.CafeteriaMealListResponse; +import ac.knu.likeknu.controller.dto.menu.MenuThumbsRequest; +import ac.knu.likeknu.controller.dto.menu.MenuThumbsStatusResponse; +import ac.knu.likeknu.domain.constants.Campus; import ac.knu.likeknu.exception.BusinessException; import ac.knu.likeknu.service.MenuService; +import ac.knu.likeknu.service.ThumbsService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.time.LocalDate; import java.util.List; @RestController -@RequestMapping("/api/menu") +@RequestMapping("/api/menus") @RequiredArgsConstructor public class MenuController { private final MenuService menuService; + private final ThumbsService thumbsService; @GetMapping - public ResponseDto> getMenuByCampus( + public ResponseDto> getMenuByCampus( @RequestParam(name = "campus") Campus campus, - @RequestParam(name = "date", defaultValue = "#{T(java.time.LocalDate).now()}") LocalDate date + @RequestParam(name = "cafeteriaName") String cafeteriaName ) { if (campus.equals(Campus.ALL)) { throw new BusinessException("Invalid campus"); } - List menuResponsesByCampus = menuService.getMenuResponsesByCampus(campus, date); - return ResponseDto.of(menuResponsesByCampus); + List cafeteriaMeals = menuService.getCafeteriaMeals(campus, cafeteriaName); + return ResponseDto.of(cafeteriaMeals); + } + + @GetMapping("/{menuId}/thumbs") + public ResponseDto getThumbsStatus( + @PathVariable(name = "menuId") String menuId, + @RequestParam(name = "deviceId") String deviceId + ) { + MenuThumbsStatusResponse menuThumbsStatus = thumbsService.getMenuThumbsStatus(menuId, deviceId); + return ResponseDto.of(menuThumbsStatus); + } + + @PutMapping("/{menuId}/thumbs") + public ResponseDto updateThumbs( + @PathVariable(name = "menuId") String menuId, + @RequestBody MenuThumbsRequest menuThumbsRequest + ) { + MenuThumbsStatusResponse updatedMenuThumbsStatus = + thumbsService.updateThumbs(menuId, menuThumbsRequest.deviceId(), menuThumbsRequest.thumbsType()); + return ResponseDto.of(updatedMenuThumbsStatus); } } diff --git a/src/main/java/ac/knu/likeknu/controller/dto/main/MainAnnouncementsResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/announcement/MainAnnouncementsResponse.java similarity index 91% rename from src/main/java/ac/knu/likeknu/controller/dto/main/MainAnnouncementsResponse.java rename to src/main/java/ac/knu/likeknu/controller/dto/announcement/MainAnnouncementsResponse.java index 3560574..f53a162 100644 --- a/src/main/java/ac/knu/likeknu/controller/dto/main/MainAnnouncementsResponse.java +++ b/src/main/java/ac/knu/likeknu/controller/dto/announcement/MainAnnouncementsResponse.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.controller.dto.main; +package ac.knu.likeknu.controller.dto.announcement; import ac.knu.likeknu.domain.Announcement; import lombok.Builder; diff --git a/src/main/java/ac/knu/likeknu/controller/dto/main/MainCityBusResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/citybus/MainCityBusResponse.java similarity index 96% rename from src/main/java/ac/knu/likeknu/controller/dto/main/MainCityBusResponse.java rename to src/main/java/ac/knu/likeknu/controller/dto/citybus/MainCityBusResponse.java index 54599ec..ad371ff 100644 --- a/src/main/java/ac/knu/likeknu/controller/dto/main/MainCityBusResponse.java +++ b/src/main/java/ac/knu/likeknu/controller/dto/citybus/MainCityBusResponse.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.controller.dto.main; +package ac.knu.likeknu.controller.dto.citybus; import ac.knu.likeknu.domain.CityBus; import ac.knu.likeknu.domain.Route; diff --git a/src/main/java/ac/knu/likeknu/controller/dto/device/response/SubscribeTagListResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/device/response/SubscribeTagListResponse.java index ff90374..c5ac2e2 100644 --- a/src/main/java/ac/knu/likeknu/controller/dto/device/response/SubscribeTagListResponse.java +++ b/src/main/java/ac/knu/likeknu/controller/dto/device/response/SubscribeTagListResponse.java @@ -1,6 +1,6 @@ package ac.knu.likeknu.controller.dto.device.response; -import ac.knu.likeknu.domain.value.Tag; +import ac.knu.likeknu.domain.constants.Tag; public record SubscribeTagListResponse(String tag) { diff --git a/src/main/java/ac/knu/likeknu/controller/dto/main/MainMenuResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/main/MainMenuResponse.java deleted file mode 100644 index 513fcd1..0000000 --- a/src/main/java/ac/knu/likeknu/controller/dto/main/MainMenuResponse.java +++ /dev/null @@ -1,39 +0,0 @@ -package ac.knu.likeknu.controller.dto.main; - -import ac.knu.likeknu.controller.dto.menu.MenuListDto; -import ac.knu.likeknu.domain.Cafeteria; -import ac.knu.likeknu.domain.value.MealType; -import lombok.Builder; - -import java.util.ArrayList; -import java.util.List; - -@Builder -public record MainMenuResponse(String cafeteriaId, String cafeteriaName, String mealType, List menus) { - - public static MainMenuResponse of(Cafeteria cafeteria, String menu) { - List menuList = new ArrayList<>(); - if (menu != null) { - String[] menus = menu.split(" "); - for (int i = 0; i < menus.length; i++) { - menuList.add(MenuListDto.of(i + 1, menus[i])); - } - } - - return MainMenuResponse.builder() - .cafeteriaId(cafeteria.getId()) - .cafeteriaName(cafeteria.getCafeteriaName()) - .mealType(MealType.now().getMealTypeKr()) - .menus(menuList) - .build(); - } - - public static MainMenuResponse empty(Cafeteria cafeteria) { - return MainMenuResponse.builder() - .cafeteriaId(cafeteria.getId()) - .cafeteriaName(cafeteria.getCafeteriaName()) - .mealType(MealType.now().getMealTypeKr()) - .menus(new ArrayList<>()) - .build(); - } -} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/CafeteriaMealListResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/CafeteriaMealListResponse.java new file mode 100644 index 0000000..0d36857 --- /dev/null +++ b/src/main/java/ac/knu/likeknu/controller/dto/menu/CafeteriaMealListResponse.java @@ -0,0 +1,15 @@ +package ac.knu.likeknu.controller.dto.menu; + +import ac.knu.likeknu.domain.Cafeteria; + +import java.time.LocalDate; +import java.util.List; + +public record CafeteriaMealListResponse(String cafeteriaId, String cafeteriaName, LocalDate date, + List meals) { + + public static CafeteriaMealListResponse of(Cafeteria cafeteria, LocalDate date, + List meals) { + return new CafeteriaMealListResponse(cafeteria.getId(), cafeteria.getCafeteriaName(), date, meals); + } +} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/MainMenuResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/MainMenuResponse.java new file mode 100644 index 0000000..4e7de59 --- /dev/null +++ b/src/main/java/ac/knu/likeknu/controller/dto/menu/MainMenuResponse.java @@ -0,0 +1,26 @@ +package ac.knu.likeknu.controller.dto.menu; + +import ac.knu.likeknu.domain.Cafeteria; +import ac.knu.likeknu.domain.constants.MealType; +import lombok.Builder; + +@Builder +public record MainMenuResponse(String cafeteriaId, String cafeteriaName, String mealType, String menus) { + + public static MainMenuResponse of(Cafeteria cafeteria, String menu) { + return MainMenuResponse.builder() + .cafeteriaId(cafeteria.getId()) + .cafeteriaName(cafeteria.getCafeteriaName()) + .mealType(MealType.now().getKorean()) + .menus(menu) + .build(); + } + + public static MainMenuResponse empty(Cafeteria cafeteria) { + return MainMenuResponse.builder() + .cafeteriaId(cafeteria.getId()) + .cafeteriaName(cafeteria.getCafeteriaName()) + .mealType(MealType.now().getKorean()) + .build(); + } +} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/MealListDto.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/MealListDto.java deleted file mode 100644 index a606337..0000000 --- a/src/main/java/ac/knu/likeknu/controller/dto/menu/MealListDto.java +++ /dev/null @@ -1,59 +0,0 @@ -package ac.knu.likeknu.controller.dto.menu; - -import ac.knu.likeknu.domain.Cafeteria; -import ac.knu.likeknu.domain.Menu; -import ac.knu.likeknu.domain.value.MealType; -import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Builder; -import lombok.Getter; - -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; - -@Getter -public class MealListDto { - - private String mealType; - private String operatingTime; - private List menus; - - @JsonIgnore - private LocalDate date; - - @Builder - public MealListDto(String mealType, String operatingTime, List menus, LocalDate date) { - this.mealType = mealType; - this.operatingTime = operatingTime; - this.menus = menus; - this.date = date; - } - - public static MealListDto of(MealType mealType, Cafeteria cafeteria, Menu menu) { - List menuList = new ArrayList<>(); - if (menu != null) { - String[] menus = menu.getMenus().split(" "); - for (int i = 0; i < menus.length; i++) { - menuList.add(MenuListDto.of(i + 1, menus[i])); - } - } - - LocalDate menuDate = menu.getMenuDate(); - return MealListDto.builder() - .mealType(mealType.getMealTypeKr()) - .operatingTime(cafeteria.getTime(mealType, menuDate)) - .menus(menuList) - .date(menuDate) - .build(); - } - - public static MealListDto empty(MealType mealType, Cafeteria cafeteria, LocalDate date) { - return MealListDto.builder() - .mealType(mealType.getMealTypeKr()) - .operatingTime(cafeteria.getTime(mealType, date)) - .menus(new ArrayList<>()) - .date(date) - .build(); - } - -} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/MealListResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/MealListResponse.java new file mode 100644 index 0000000..40da1f5 --- /dev/null +++ b/src/main/java/ac/knu/likeknu/controller/dto/menu/MealListResponse.java @@ -0,0 +1,23 @@ +package ac.knu.likeknu.controller.dto.menu; + +import ac.knu.likeknu.domain.Cafeteria; +import ac.knu.likeknu.domain.Menu; +import ac.knu.likeknu.domain.constants.MealType; +import lombok.Builder; + +@Builder +public record MealListResponse(String menuId, String mealType, String operatingTime, String menus) { + + public static MealListResponse of(Menu menu, Cafeteria cafeteria) { + MealType mealType = menu.getMealType(); + String operatingTime = cafeteria.getOperatingTime(mealType, menu.getMenuDate()); + return new MealListResponse(menu.getId(), mealType.getKorean(), operatingTime, menu.getMenus()); + } + + public static MealListResponse empty(MealType mealType, String operatingTime) { + return MealListResponse.builder() + .mealType(mealType.getKorean()) + .operatingTime(operatingTime) + .build(); + } +} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuListDto.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuListDto.java deleted file mode 100644 index 7bfed5b..0000000 --- a/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuListDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package ac.knu.likeknu.controller.dto.menu; - -import lombok.Getter; - -@Getter -public class MenuListDto { - - private final int menuId; - private final String menuName; - - public MenuListDto(int menuId, String menuName) { - this.menuId = menuId; - this.menuName = menuName; - } - - public static MenuListDto of(int index, String menuName) { - return new MenuListDto(index, menuName); - } -} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuResponse.java deleted file mode 100644 index 7613581..0000000 --- a/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -package ac.knu.likeknu.controller.dto.menu; - -import ac.knu.likeknu.domain.Cafeteria; -import lombok.Builder; -import lombok.Getter; - -import java.time.LocalDate; -import java.util.List; -import java.util.Map; - -@Getter -public class MenuResponse { - - private String cafeteriaId; - private String cafeteriaName; - private List today; - private List tomorrow; - - @Builder - public MenuResponse(String cafeteriaId, String cafeteriaName, List today, List tomorrow) { - this.cafeteriaId = cafeteriaId; - this.cafeteriaName = cafeteriaName; - this.today = today; - this.tomorrow = tomorrow; - } - - public static MenuResponse of(Cafeteria cafeteria, Map> mealList) { - List keys = mealList.keySet() - .stream() - .sorted() - .toList(); - - return MenuResponse.builder() - .cafeteriaId(cafeteria.getId()) - .cafeteriaName(cafeteria.getCafeteriaName()) - .today(mealList.get(keys.get(0))) - .tomorrow(mealList.get(keys.get(1))) - .build(); - } -} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuThumbsRequest.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuThumbsRequest.java new file mode 100644 index 0000000..8cf4201 --- /dev/null +++ b/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuThumbsRequest.java @@ -0,0 +1,6 @@ +package ac.knu.likeknu.controller.dto.menu; + +import ac.knu.likeknu.domain.constants.ThumbsType; + +public record MenuThumbsRequest(String deviceId, ThumbsType thumbsType) { +} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuThumbsStatusResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuThumbsStatusResponse.java new file mode 100644 index 0000000..a0bbc0c --- /dev/null +++ b/src/main/java/ac/knu/likeknu/controller/dto/menu/MenuThumbsStatusResponse.java @@ -0,0 +1,4 @@ +package ac.knu.likeknu.controller.dto.menu; + +public record MenuThumbsStatusResponse(int thumbsUp, int thumbsDown, String ownThumbs) { +} diff --git a/src/main/java/ac/knu/likeknu/controller/dto/main/MainScheduleResponse.java b/src/main/java/ac/knu/likeknu/controller/dto/schedule/MainScheduleResponse.java similarity index 96% rename from src/main/java/ac/knu/likeknu/controller/dto/main/MainScheduleResponse.java rename to src/main/java/ac/knu/likeknu/controller/dto/schedule/MainScheduleResponse.java index 81cf035..0c1226b 100644 --- a/src/main/java/ac/knu/likeknu/controller/dto/main/MainScheduleResponse.java +++ b/src/main/java/ac/knu/likeknu/controller/dto/schedule/MainScheduleResponse.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.controller.dto.main; +package ac.knu.likeknu.controller.dto.schedule; import ac.knu.likeknu.domain.AcademicCalendar; import lombok.Builder; diff --git a/src/main/java/ac/knu/likeknu/domain/Announcement.java b/src/main/java/ac/knu/likeknu/domain/Announcement.java index f24fccd..a68c962 100644 --- a/src/main/java/ac/knu/likeknu/domain/Announcement.java +++ b/src/main/java/ac/knu/likeknu/domain/Announcement.java @@ -1,8 +1,8 @@ package ac.knu.likeknu.domain; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Category; -import ac.knu.likeknu.domain.value.Tag; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Category; +import ac.knu.likeknu.domain.constants.Tag; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; diff --git a/src/main/java/ac/knu/likeknu/domain/Cafeteria.java b/src/main/java/ac/knu/likeknu/domain/Cafeteria.java index b02b9ba..277d64a 100644 --- a/src/main/java/ac/knu/likeknu/domain/Cafeteria.java +++ b/src/main/java/ac/knu/likeknu/domain/Cafeteria.java @@ -1,7 +1,7 @@ package ac.knu.likeknu.domain; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.MealType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.MealType; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -46,41 +46,40 @@ public class Cafeteria { protected Cafeteria() { } - public String getTime(MealType mealType, LocalDate date) { - if (mealType == null) - return null; + public boolean isOperate(MealType mealType, LocalDate date) { + String operatingTime = getOperatingTime(mealType, date); + return operatingTime != null; + } + public String getOperatingTime(MealType mealType, LocalDate date) { if (isWeekend(date)) { - //주말일 때 - if (isBreakfast(mealType)) + if (mealType.equals(MealType.BREAKFAST)) { return weekendBreakfast; - else if (isLunch(mealType)) + } + if (mealType.equals(MealType.LUNCH)) { return weekendLunch; - else + } + if (mealType.equals(MealType.DINNER)) return weekendDinner; } else { - //평일일 때 - if (isBreakfast(mealType)) + if (mealType.equals(MealType.BREAKFAST)) { return weekdayBreakfast; - else if (isLunch(mealType)) + } + if (mealType.equals(MealType.LUNCH)) { return weekdayLunch; - else + } + if (mealType.equals(MealType.DINNER)) { return weekdayDinner; + } } + return null; } + private boolean isWeekend(LocalDate date) { return date.getDayOfWeek().getValue() >= 6; } - private boolean isBreakfast(MealType mealType) { - return mealType.equals(MealType.BREAKFAST); - } - - private boolean isLunch(MealType mealType) { - return mealType.equals(MealType.LUNCH); - } - @Override public boolean equals(Object object) { if (this == object) return true; diff --git a/src/main/java/ac/knu/likeknu/domain/Device.java b/src/main/java/ac/knu/likeknu/domain/Device.java index f0f4328..6b3108f 100644 --- a/src/main/java/ac/knu/likeknu/domain/Device.java +++ b/src/main/java/ac/knu/likeknu/domain/Device.java @@ -1,8 +1,8 @@ package ac.knu.likeknu.domain; import ac.knu.likeknu.controller.dto.device.request.DeviceRegistrationRequest; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Tag; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Tag; import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; import jakarta.persistence.ElementCollection; diff --git a/src/main/java/ac/knu/likeknu/domain/Menu.java b/src/main/java/ac/knu/likeknu/domain/Menu.java index a2489b6..33e2a0c 100644 --- a/src/main/java/ac/knu/likeknu/domain/Menu.java +++ b/src/main/java/ac/knu/likeknu/domain/Menu.java @@ -1,6 +1,6 @@ package ac.knu.likeknu.domain; -import ac.knu.likeknu.domain.value.MealType; +import ac.knu.likeknu.domain.constants.MealType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; diff --git a/src/main/java/ac/knu/likeknu/domain/MenuThumbs.java b/src/main/java/ac/knu/likeknu/domain/MenuThumbs.java new file mode 100644 index 0000000..5274ed5 --- /dev/null +++ b/src/main/java/ac/knu/likeknu/domain/MenuThumbs.java @@ -0,0 +1,66 @@ +package ac.knu.likeknu.domain; + +import ac.knu.likeknu.domain.constants.ThumbsType; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; + +import java.sql.Timestamp; + +@Getter +@Table(name = "menu_thumbs") +@Entity +public class MenuThumbs { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Enumerated(EnumType.STRING) + private ThumbsType thumbsType; + + private Timestamp thumbsAt; + + @JoinColumn(name = "device") + @ManyToOne(fetch = FetchType.LAZY) + private Device device; + + @JoinColumn(name = "menu") + @ManyToOne(fetch = FetchType.LAZY) + private Menu menu; + + protected MenuThumbs() { + } + + @Builder + public MenuThumbs(ThumbsType thumbsType, Device device, Menu menu) { + this.thumbsType = thumbsType; + this.thumbsAt = new Timestamp(System.currentTimeMillis()); + this.device = device; + this.menu = menu; + } + + public String getType() { + return thumbsType.name(); + } + + public boolean isTypeOf(ThumbsType thumbsType) { + return this.thumbsType.equals(thumbsType); + } + + public void changeType(ThumbsType thumbsType) { + if (thumbsType != null) { + this.thumbsType = thumbsType; + } + thumbsAt = new Timestamp(System.currentTimeMillis()); + } +} diff --git a/src/main/java/ac/knu/likeknu/domain/Route.java b/src/main/java/ac/knu/likeknu/domain/Route.java index 2196876..c12a757 100644 --- a/src/main/java/ac/knu/likeknu/domain/Route.java +++ b/src/main/java/ac/knu/likeknu/domain/Route.java @@ -1,7 +1,7 @@ package ac.knu.likeknu.domain; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.RouteType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.RouteType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; diff --git a/src/main/java/ac/knu/likeknu/domain/Shuttle.java b/src/main/java/ac/knu/likeknu/domain/Shuttle.java index 4c96501..ec76fb9 100644 --- a/src/main/java/ac/knu/likeknu/domain/Shuttle.java +++ b/src/main/java/ac/knu/likeknu/domain/Shuttle.java @@ -1,7 +1,7 @@ package ac.knu.likeknu.domain; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.ShuttleType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.ShuttleType; import jakarta.persistence.CollectionTable; import jakarta.persistence.Column; import jakarta.persistence.ElementCollection; diff --git a/src/main/java/ac/knu/likeknu/domain/value/Campus.java b/src/main/java/ac/knu/likeknu/domain/constants/Campus.java similarity index 67% rename from src/main/java/ac/knu/likeknu/domain/value/Campus.java rename to src/main/java/ac/knu/likeknu/domain/constants/Campus.java index 3bfc924..6f4d752 100644 --- a/src/main/java/ac/knu/likeknu/domain/value/Campus.java +++ b/src/main/java/ac/knu/likeknu/domain/constants/Campus.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.domain.value; +package ac.knu.likeknu.domain.constants; import lombok.Getter; @@ -12,17 +12,17 @@ public enum Campus { CHEONAN("천안캠", "c-notice"), YESAN("예산캠", "y-notice"); - private final String campus; + private final String name; private final String dormitoryAnnouncementId; - Campus(String campus, String dormitoryAnnouncementId) { - this.campus = campus; + Campus(String name, String dormitoryAnnouncementId) { + this.name = name; this.dormitoryAnnouncementId = dormitoryAnnouncementId; } public static Campus of(String campusName) { return Arrays.stream(values()) - .filter(campus -> campus.getCampus().equals(campusName)) + .filter(campus -> campus.getName().equals(campusName)) .findAny() .orElseThrow(); } diff --git a/src/main/java/ac/knu/likeknu/domain/value/Category.java b/src/main/java/ac/knu/likeknu/domain/constants/Category.java similarity index 94% rename from src/main/java/ac/knu/likeknu/domain/value/Category.java rename to src/main/java/ac/knu/likeknu/domain/constants/Category.java index 4c9c8ba..f8c37a4 100644 --- a/src/main/java/ac/knu/likeknu/domain/value/Category.java +++ b/src/main/java/ac/knu/likeknu/domain/constants/Category.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.domain.value; +package ac.knu.likeknu.domain.constants; import lombok.Getter; diff --git a/src/main/java/ac/knu/likeknu/domain/value/MealType.java b/src/main/java/ac/knu/likeknu/domain/constants/MealType.java similarity index 68% rename from src/main/java/ac/knu/likeknu/domain/value/MealType.java rename to src/main/java/ac/knu/likeknu/domain/constants/MealType.java index 2823ce0..ceb58da 100644 --- a/src/main/java/ac/knu/likeknu/domain/value/MealType.java +++ b/src/main/java/ac/knu/likeknu/domain/constants/MealType.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.domain.value; +package ac.knu.likeknu.domain.constants; import lombok.Getter; @@ -12,11 +12,11 @@ public enum MealType { LUNCH("점심", 14), DINNER("저녁", 19); - private final String mealTypeKr; + private final String korean; private final int hour; - MealType(String mealTypeKr, int hour) { - this.mealTypeKr = mealTypeKr; + MealType(String korean, int hour) { + this.korean = korean; this.hour = hour; } @@ -25,7 +25,7 @@ public static MealType now() { .getHour(); return Stream.of(MealType.values()) - .filter((MealType m) -> m.getHour() > hour) + .filter(mealType -> mealType.getHour() > hour) .findFirst() .orElse(DINNER); } diff --git a/src/main/java/ac/knu/likeknu/domain/value/RouteType.java b/src/main/java/ac/knu/likeknu/domain/constants/RouteType.java similarity index 94% rename from src/main/java/ac/knu/likeknu/domain/value/RouteType.java rename to src/main/java/ac/knu/likeknu/domain/constants/RouteType.java index 0751de6..96bde78 100644 --- a/src/main/java/ac/knu/likeknu/domain/value/RouteType.java +++ b/src/main/java/ac/knu/likeknu/domain/constants/RouteType.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.domain.value; +package ac.knu.likeknu.domain.constants; import ac.knu.likeknu.exception.BusinessException; import ac.knu.likeknu.exception.ErrorMessage; diff --git a/src/main/java/ac/knu/likeknu/domain/value/ShuttleType.java b/src/main/java/ac/knu/likeknu/domain/constants/ShuttleType.java similarity index 91% rename from src/main/java/ac/knu/likeknu/domain/value/ShuttleType.java rename to src/main/java/ac/knu/likeknu/domain/constants/ShuttleType.java index a38ca7f..7834fdb 100644 --- a/src/main/java/ac/knu/likeknu/domain/value/ShuttleType.java +++ b/src/main/java/ac/knu/likeknu/domain/constants/ShuttleType.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.domain.value; +package ac.knu.likeknu.domain.constants; import ac.knu.likeknu.exception.BusinessException; diff --git a/src/main/java/ac/knu/likeknu/domain/value/Tag.java b/src/main/java/ac/knu/likeknu/domain/constants/Tag.java similarity index 94% rename from src/main/java/ac/knu/likeknu/domain/value/Tag.java rename to src/main/java/ac/knu/likeknu/domain/constants/Tag.java index 398bc05..6ed6eeb 100644 --- a/src/main/java/ac/knu/likeknu/domain/value/Tag.java +++ b/src/main/java/ac/knu/likeknu/domain/constants/Tag.java @@ -1,4 +1,4 @@ -package ac.knu.likeknu.domain.value; +package ac.knu.likeknu.domain.constants; import ac.knu.likeknu.exception.BusinessException; import lombok.Getter; diff --git a/src/main/java/ac/knu/likeknu/domain/constants/ThumbsType.java b/src/main/java/ac/knu/likeknu/domain/constants/ThumbsType.java new file mode 100644 index 0000000..0be207c --- /dev/null +++ b/src/main/java/ac/knu/likeknu/domain/constants/ThumbsType.java @@ -0,0 +1,6 @@ +package ac.knu.likeknu.domain.constants; + +public enum ThumbsType { + + THUMBS_UP, THUMBS_DOWN +} diff --git a/src/main/java/ac/knu/likeknu/exception/BusinessExceptionHandler.java b/src/main/java/ac/knu/likeknu/exception/BusinessExceptionHandler.java deleted file mode 100644 index 1151eb9..0000000 --- a/src/main/java/ac/knu/likeknu/exception/BusinessExceptionHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -package ac.knu.likeknu.exception; - -import ac.knu.likeknu.service.SlackService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@Slf4j -@RestControllerAdvice -public class BusinessExceptionHandler { - - private final SlackService slackService; - - public BusinessExceptionHandler(SlackService slackService) { - this.slackService = slackService; - } - - @ExceptionHandler(value = BusinessException.class) - protected ResponseEntity businessExceptionHandler(BusinessException exception) { - String message = exception.getMessage(); - log.info("sd", exception); - slackService.sendMessage(message); - return ResponseEntity.badRequest().body(message); - } -} diff --git a/src/main/java/ac/knu/likeknu/exception/ExceptionControllerAdvice.java b/src/main/java/ac/knu/likeknu/exception/ExceptionControllerAdvice.java new file mode 100644 index 0000000..57986fa --- /dev/null +++ b/src/main/java/ac/knu/likeknu/exception/ExceptionControllerAdvice.java @@ -0,0 +1,39 @@ +package ac.knu.likeknu.exception; + +import ac.knu.likeknu.service.SlackService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class ExceptionControllerAdvice { + + private final SlackService slackService; + + public ExceptionControllerAdvice(SlackService slackService) { + this.slackService = slackService; + } + + @ExceptionHandler(value = BusinessException.class) + protected ResponseEntity businessExceptionHandler(BusinessException exception) { + String message = exception.getMessage(); + log.info("BusinessException: ", exception); + slackService.sendMessage(message); + return ResponseEntity.badRequest() + .body(message); + } + + /*@ExceptionHandler(value = Exception.class) + protected ResponseEntity exceptionHandler(Exception exception) { + String message = exception.getMessage(); + String stackTrace = Arrays.stream(exception.getStackTrace()) + .map(StackTraceElement::toString) + .collect(Collectors.joining()); + log.error("Exception: ", exception); + slackService.sendMessage(String.join("\n", message, stackTrace)); + return ResponseEntity.internalServerError() + .body(message); + }*/ +} diff --git a/src/main/java/ac/knu/likeknu/repository/AnnouncementRepository.java b/src/main/java/ac/knu/likeknu/repository/AnnouncementRepository.java index d060cf3..28ee4be 100644 --- a/src/main/java/ac/knu/likeknu/repository/AnnouncementRepository.java +++ b/src/main/java/ac/knu/likeknu/repository/AnnouncementRepository.java @@ -1,8 +1,8 @@ package ac.knu.likeknu.repository; import ac.knu.likeknu.domain.Announcement; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Category; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Category; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; diff --git a/src/main/java/ac/knu/likeknu/repository/CafeteriaRepository.java b/src/main/java/ac/knu/likeknu/repository/CafeteriaRepository.java index 868d05a..4dfee06 100644 --- a/src/main/java/ac/knu/likeknu/repository/CafeteriaRepository.java +++ b/src/main/java/ac/knu/likeknu/repository/CafeteriaRepository.java @@ -1,7 +1,7 @@ package ac.knu.likeknu.repository; import ac.knu.likeknu.domain.Cafeteria; -import ac.knu.likeknu.domain.value.Campus; +import ac.knu.likeknu.domain.constants.Campus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/src/main/java/ac/knu/likeknu/repository/MenuRepository.java b/src/main/java/ac/knu/likeknu/repository/MenuRepository.java index 1170ba7..c4cb5ff 100644 --- a/src/main/java/ac/knu/likeknu/repository/MenuRepository.java +++ b/src/main/java/ac/knu/likeknu/repository/MenuRepository.java @@ -2,15 +2,14 @@ import ac.knu.likeknu.domain.Cafeteria; import ac.knu.likeknu.domain.Menu; -import ac.knu.likeknu.domain.value.MealType; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.time.LocalDate; -import java.util.Optional; +import java.util.List; @Repository public interface MenuRepository extends JpaRepository { - Optional findByMenuDateAndCafeteriaAndMealType(LocalDate menuDate, Cafeteria cafeteria, MealType mealType); + List findByCafeteriaAndMenuDate(Cafeteria cafeteria, LocalDate menuDate); } diff --git a/src/main/java/ac/knu/likeknu/repository/MenuThumbsRepository.java b/src/main/java/ac/knu/likeknu/repository/MenuThumbsRepository.java new file mode 100644 index 0000000..1776707 --- /dev/null +++ b/src/main/java/ac/knu/likeknu/repository/MenuThumbsRepository.java @@ -0,0 +1,18 @@ +package ac.knu.likeknu.repository; + +import ac.knu.likeknu.domain.Device; +import ac.knu.likeknu.domain.Menu; +import ac.knu.likeknu.domain.MenuThumbs; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Optional; + +public interface MenuThumbsRepository extends JpaRepository { + + @EntityGraph(attributePaths = "device") + List findByMenu(Menu menu); + + Optional findByMenuAndDevice(Menu menu, Device device); +} diff --git a/src/main/java/ac/knu/likeknu/repository/RouteRepository.java b/src/main/java/ac/knu/likeknu/repository/RouteRepository.java index 0ccd44d..88cfe09 100644 --- a/src/main/java/ac/knu/likeknu/repository/RouteRepository.java +++ b/src/main/java/ac/knu/likeknu/repository/RouteRepository.java @@ -1,8 +1,8 @@ package ac.knu.likeknu.repository; import ac.knu.likeknu.domain.Route; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.RouteType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.RouteType; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; diff --git a/src/main/java/ac/knu/likeknu/repository/ShuttleRepository.java b/src/main/java/ac/knu/likeknu/repository/ShuttleRepository.java index ab442ff..4bb7d0b 100644 --- a/src/main/java/ac/knu/likeknu/repository/ShuttleRepository.java +++ b/src/main/java/ac/knu/likeknu/repository/ShuttleRepository.java @@ -1,7 +1,7 @@ package ac.knu.likeknu.repository; import ac.knu.likeknu.domain.Shuttle; -import ac.knu.likeknu.domain.value.Campus; +import ac.knu.likeknu.domain.constants.Campus; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; diff --git a/src/main/java/ac/knu/likeknu/service/AnnouncementService.java b/src/main/java/ac/knu/likeknu/service/AnnouncementService.java index ec9f509..057afb5 100644 --- a/src/main/java/ac/knu/likeknu/service/AnnouncementService.java +++ b/src/main/java/ac/knu/likeknu/service/AnnouncementService.java @@ -3,8 +3,8 @@ import ac.knu.likeknu.controller.dto.announcement.AnnouncementListResponse; import ac.knu.likeknu.controller.dto.base.PageDto; import ac.knu.likeknu.domain.Announcement; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Category; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Category; import ac.knu.likeknu.repository.AnnouncementRepository; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; diff --git a/src/main/java/ac/knu/likeknu/service/CityBusService.java b/src/main/java/ac/knu/likeknu/service/CityBusService.java index 9fb5cf2..c6a3b75 100644 --- a/src/main/java/ac/knu/likeknu/service/CityBusService.java +++ b/src/main/java/ac/knu/likeknu/service/CityBusService.java @@ -2,11 +2,11 @@ import ac.knu.likeknu.controller.dto.citybus.CityBusesArrivalTimeResponse; import ac.knu.likeknu.controller.dto.citybus.CityBusesResponse; -import ac.knu.likeknu.controller.dto.main.MainCityBusResponse; +import ac.knu.likeknu.controller.dto.citybus.MainCityBusResponse; import ac.knu.likeknu.domain.CityBus; import ac.knu.likeknu.domain.Route; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.RouteType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.RouteType; import ac.knu.likeknu.repository.CityBusRepository; import ac.knu.likeknu.repository.RouteRepository; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/ac/knu/likeknu/service/DeviceService.java b/src/main/java/ac/knu/likeknu/service/DeviceService.java index 8d3fc10..7e01728 100644 --- a/src/main/java/ac/knu/likeknu/service/DeviceService.java +++ b/src/main/java/ac/knu/likeknu/service/DeviceService.java @@ -8,8 +8,8 @@ import ac.knu.likeknu.controller.dto.device.request.TagName; import ac.knu.likeknu.controller.dto.device.response.SubscribeTagListResponse; import ac.knu.likeknu.domain.Device; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Tag; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Tag; import ac.knu.likeknu.exception.BusinessException; import ac.knu.likeknu.repository.DeviceRepository; import org.springframework.stereotype.Service; diff --git a/src/main/java/ac/knu/likeknu/service/MainService.java b/src/main/java/ac/knu/likeknu/service/MainService.java index 25b1b31..e970389 100644 --- a/src/main/java/ac/knu/likeknu/service/MainService.java +++ b/src/main/java/ac/knu/likeknu/service/MainService.java @@ -1,14 +1,15 @@ package ac.knu.likeknu.service; -import ac.knu.likeknu.controller.dto.main.MainAnnouncementsResponse; -import ac.knu.likeknu.controller.dto.main.MainMenuResponse; -import ac.knu.likeknu.controller.dto.main.MainScheduleResponse; +import ac.knu.likeknu.controller.dto.announcement.MainAnnouncementsResponse; +import ac.knu.likeknu.controller.dto.menu.MainMenuResponse; +import ac.knu.likeknu.controller.dto.schedule.MainScheduleResponse; import ac.knu.likeknu.domain.AcademicCalendar; import ac.knu.likeknu.domain.Announcement; import ac.knu.likeknu.domain.Cafeteria; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Category; -import ac.knu.likeknu.domain.value.MealType; +import ac.knu.likeknu.domain.Menu; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Category; +import ac.knu.likeknu.domain.constants.MealType; import ac.knu.likeknu.repository.AcademicCalendarRepository; import ac.knu.likeknu.repository.AnnouncementRepository; import ac.knu.likeknu.repository.CafeteriaRepository; @@ -23,6 +24,7 @@ import java.time.LocalDate; import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @Slf4j @@ -49,11 +51,20 @@ public List getAnnouncementsResponse(Campus campus) { } public List getMenuResponse(Campus campus) { - List cafeterias = cafeteriaRepository.findByCampus(campus); - return cafeterias.stream() + return cafeteriaRepository.findByCampus(campus) + .stream() .sorted(Comparator.comparing(Cafeteria::getSequence)) - .map(this::findAndGenerateMenuResponse) - .collect(Collectors.toList()); + .map(cafeteria -> findNowMealTypeMenu(cafeteria) + .map(menu -> MainMenuResponse.of(cafeteria, menu.getMenus())) + .orElse(MainMenuResponse.empty(cafeteria))) + .toList(); + } + + private Optional findNowMealTypeMenu(Cafeteria cafeteria) { + return menuRepository.findByCafeteriaAndMenuDate(cafeteria, LocalDate.now()) + .stream() + .filter(menu -> menu.getMealType().equals(MealType.now())) + .findAny(); } public List getScheduleResponse() { @@ -65,10 +76,4 @@ public List getScheduleResponse() { .map(MainScheduleResponse::of) .collect(Collectors.toList()); } - - private MainMenuResponse findAndGenerateMenuResponse(Cafeteria cafeteria) { - return menuRepository.findByMenuDateAndCafeteriaAndMealType(LocalDate.now(), cafeteria, MealType.now()) - .map(menu -> MainMenuResponse.of(cafeteria, menu.getMenus())) - .orElse(MainMenuResponse.empty(cafeteria)); - } } diff --git a/src/main/java/ac/knu/likeknu/service/MenuService.java b/src/main/java/ac/knu/likeknu/service/MenuService.java index cbdcff4..985c711 100644 --- a/src/main/java/ac/knu/likeknu/service/MenuService.java +++ b/src/main/java/ac/knu/likeknu/service/MenuService.java @@ -1,10 +1,12 @@ package ac.knu.likeknu.service; -import ac.knu.likeknu.controller.dto.menu.MealListDto; -import ac.knu.likeknu.controller.dto.menu.MenuResponse; +import ac.knu.likeknu.controller.dto.menu.CafeteriaMealListResponse; +import ac.knu.likeknu.controller.dto.menu.MealListResponse; import ac.knu.likeknu.domain.Cafeteria; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.MealType; +import ac.knu.likeknu.domain.Menu; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.MealType; +import ac.knu.likeknu.exception.BusinessException; import ac.knu.likeknu.repository.CafeteriaRepository; import ac.knu.likeknu.repository.MenuRepository; import lombok.RequiredArgsConstructor; @@ -14,10 +16,8 @@ import java.time.LocalDate; import java.util.Arrays; -import java.util.Comparator; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; +import java.util.Optional; import java.util.stream.Stream; @Slf4j @@ -29,28 +29,42 @@ public class MenuService { private final MenuRepository menuRepository; private final CafeteriaRepository cafeteriaRepository; - public List getMenuResponsesByCampus(Campus campus, LocalDate date) { - List cafeterias = cafeteriaRepository.findByCampus(campus); + public List getCafeteriaMeals(Campus campus, String cafeteriaName) { + Cafeteria specifiedCafeteria = cafeteriaRepository.findByCampus(campus) + .stream() + .filter(cafeteria -> cafeteria.getCafeteriaName().equals(cafeteriaName)) + .findAny() + .orElseThrow(() -> new BusinessException( + String.format("cafeteria name does not exist [%s], on campus [%s]", cafeteriaName, campus.getName())) + ); - return cafeterias.stream() - .sorted(Comparator.comparing(Cafeteria::getSequence)) - .map(cafeteria -> MenuResponse.of(cafeteria, createMapContainingMealListDto(cafeteria, date))) - .collect(Collectors.toList()); + LocalDate startDate = LocalDate.now(); + LocalDate endDate = LocalDate.now() + .plusDays(1); + return getPeriodCafeteriaMealList(specifiedCafeteria, startDate, endDate); } - private Map> createMapContainingMealListDto(Cafeteria cafeteria, LocalDate date) { - return Arrays.stream(MealType.values()) - .flatMap(mealType -> Stream.of(date, date.plusDays(1)) - .map(day -> findRepositoryAndMapDto(mealType, cafeteria, day))) - .collect( - Collectors.groupingBy(MealListDto::getDate, - Collectors.mapping(mealListDto -> mealListDto, Collectors.toList()) - )); + private List getPeriodCafeteriaMealList(Cafeteria specifiedCafeteria, LocalDate startDate, LocalDate endDate) { + return Stream.iterate(startDate, date -> date.isBefore(endDate.plusDays(1)), + date -> date.plusDays(1)) + .map(date -> getOneDayCafeteriaMealList(specifiedCafeteria, date)) + .toList(); } - private MealListDto findRepositoryAndMapDto(MealType mealType, Cafeteria cafeteria, LocalDate date) { - return menuRepository.findByMenuDateAndCafeteriaAndMealType(date, cafeteria, mealType) - .map(menu -> MealListDto.of(mealType, cafeteria, menu)) - .orElse(MealListDto.empty(mealType, cafeteria, date)); + private CafeteriaMealListResponse getOneDayCafeteriaMealList(Cafeteria cafeteria, LocalDate date) { + List menus = menuRepository.findByCafeteriaAndMenuDate(cafeteria, date); + List mealList = Arrays.stream(MealType.values()) + .filter(mealType -> cafeteria.isOperate(mealType, date)) + .map(mealType -> mealFiltering(menus, mealType) + .map(menu -> MealListResponse.of(menu, cafeteria)) + .orElse(MealListResponse.empty(mealType, cafeteria.getOperatingTime(mealType, date)))) + .toList(); + return CafeteriaMealListResponse.of(cafeteria, date, mealList); + } + + private Optional mealFiltering(List menus, MealType mealType) { + return menus.stream() + .filter(menu -> menu.getMealType().equals(mealType)) + .findAny(); } } diff --git a/src/main/java/ac/knu/likeknu/service/ShuttleBusService.java b/src/main/java/ac/knu/likeknu/service/ShuttleBusService.java index db7696f..0cf4eb4 100644 --- a/src/main/java/ac/knu/likeknu/service/ShuttleBusService.java +++ b/src/main/java/ac/knu/likeknu/service/ShuttleBusService.java @@ -4,7 +4,7 @@ import ac.knu.likeknu.controller.dto.shuttlebus.ShuttleListResponse; import ac.knu.likeknu.domain.Shuttle; import ac.knu.likeknu.domain.ShuttleBus; -import ac.knu.likeknu.domain.value.Campus; +import ac.knu.likeknu.domain.constants.Campus; import ac.knu.likeknu.exception.BusinessException; import ac.knu.likeknu.repository.ShuttleBusRepository; import ac.knu.likeknu.repository.ShuttleRepository; diff --git a/src/main/java/ac/knu/likeknu/service/ThumbsService.java b/src/main/java/ac/knu/likeknu/service/ThumbsService.java new file mode 100644 index 0000000..eef55e3 --- /dev/null +++ b/src/main/java/ac/knu/likeknu/service/ThumbsService.java @@ -0,0 +1,97 @@ +package ac.knu.likeknu.service; + +import ac.knu.likeknu.controller.dto.menu.MenuThumbsStatusResponse; +import ac.knu.likeknu.domain.Device; +import ac.knu.likeknu.domain.Menu; +import ac.knu.likeknu.domain.MenuThumbs; +import ac.knu.likeknu.domain.constants.ThumbsType; +import ac.knu.likeknu.exception.BusinessException; +import ac.knu.likeknu.repository.DeviceRepository; +import ac.knu.likeknu.repository.MenuRepository; +import ac.knu.likeknu.repository.MenuThumbsRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +@Slf4j +@Transactional +@Service +public class ThumbsService { + + private final MenuThumbsRepository menuThumbsRepository; + private final DeviceRepository deviceRepository; + private final MenuRepository menuRepository; + + public ThumbsService(MenuThumbsRepository menuThumbsRepository, DeviceRepository deviceRepository, MenuRepository menuRepository) { + this.menuThumbsRepository = menuThumbsRepository; + this.deviceRepository = deviceRepository; + this.menuRepository = menuRepository; + } + + @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) + public MenuThumbsStatusResponse getMenuThumbsStatus(String menuId, String deviceId) { + Device device = deviceRepository.findById(deviceId) + .orElseThrow(() -> new BusinessException(String.format("device does not exist [%s]", deviceId))); + Menu menu = menuRepository.findById(menuId) + .orElseThrow(() -> new BusinessException(String.format("menu does not exist [%s]", menuId))); + + List thumbsList = menuThumbsRepository.findByMenu(menu); + Map> thumbsGroup = thumbsList.stream() + .collect(Collectors.groupingBy(MenuThumbs::getThumbsType)); + + int thumbsUpCount = getThumbsCount(thumbsGroup, ThumbsType.THUMBS_UP); + int thumbsDownCount = getThumbsCount(thumbsGroup, ThumbsType.THUMBS_DOWN); + + String ownThumbs = findOwnThumbsType(thumbsList, device); + return new MenuThumbsStatusResponse(thumbsUpCount, thumbsDownCount, ownThumbs); + } + + private int getThumbsCount(Map> thumbsGroup, ThumbsType thumbsUp) { + return thumbsGroup + .getOrDefault(thumbsUp, new ArrayList<>()) + .size(); + } + + private String findOwnThumbsType(List thumbsList, Device device) { + return thumbsList.stream() + .filter(thumbs -> thumbs.getDevice().equals(device)) + .findAny() + .map(MenuThumbs::getType) + .orElse(null); + } + + public MenuThumbsStatusResponse updateThumbs(String menuId, String deviceId, ThumbsType thumbsType) { + Device device = deviceRepository.findById(deviceId) + .orElseThrow(() -> new BusinessException(String.format("device does not exist [%s]", deviceId))); + Menu menu = menuRepository.findById(menuId) + .orElseThrow(() -> new BusinessException(String.format("menu does not exist [%s]", menuId))); + + Optional ownThumbs = menuThumbsRepository.findByMenuAndDevice(menu, device); + ownThumbs.ifPresentOrElse(thumbs -> changeThumbs(thumbs, thumbsType), () -> createThumbs(menu, device, thumbsType)); + return getMenuThumbsStatus(menuId, deviceId); + } + + private void changeThumbs(MenuThumbs thumbs, ThumbsType thumbsType) { + if (thumbs.isTypeOf(thumbsType)) { + menuThumbsRepository.delete(thumbs); + return; + } + thumbs.changeType(thumbsType); + } + + private void createThumbs(Menu menu, Device device, ThumbsType thumbsType) { + MenuThumbs menuThumbs = MenuThumbs.builder() + .thumbsType(thumbsType) + .menu(menu) + .device(device) + .build(); + menuThumbsRepository.save(menuThumbs); + } +} diff --git a/src/main/resources/db/migration/mysql/V7__add_menu_thumbs_table.sql b/src/main/resources/db/migration/mysql/V7__add_menu_thumbs_table.sql new file mode 100644 index 0000000..4630ed4 --- /dev/null +++ b/src/main/resources/db/migration/mysql/V7__add_menu_thumbs_table.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS menu_thumbs +( + id BIGINT NOT NULL AUTO_INCREMENT, + thumbs_type ENUM ('THUMBS_UP', 'THUMBS_DOWN') NOT NULL, + thumbs_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + device VARCHAR(36) NOT NULL, + menu VARCHAR(60) NOT NULL, + PRIMARY KEY (id), + FOREIGN KEY (device) REFERENCES device (id) ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (menu) REFERENCES menu (id) ON DELETE CASCADE ON UPDATE CASCADE +); + +ALTER TABLE menu_thumbs + ADD UNIQUE INDEX device_menu_uix (device, menu); diff --git a/src/test/java/ac/knu/likeknu/controller/AnnouncementControllerTest.java b/src/test/java/ac/knu/likeknu/controller/AnnouncementControllerTest.java index fc6fcfc..95de8f4 100644 --- a/src/test/java/ac/knu/likeknu/controller/AnnouncementControllerTest.java +++ b/src/test/java/ac/knu/likeknu/controller/AnnouncementControllerTest.java @@ -3,9 +3,9 @@ import ac.knu.likeknu.controller.dto.announcement.AnnouncementListResponse; import ac.knu.likeknu.controller.dto.base.PageDto; import ac.knu.likeknu.domain.Announcement; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Category; -import ac.knu.likeknu.domain.value.Tag; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Category; +import ac.knu.likeknu.domain.constants.Tag; import ac.knu.likeknu.logging.service.LoggingService; import ac.knu.likeknu.service.AnnouncementService; import ac.knu.likeknu.service.SlackService; diff --git a/src/test/java/ac/knu/likeknu/controller/BusControllerTest.java b/src/test/java/ac/knu/likeknu/controller/BusControllerTest.java index dbd7250..c79051e 100644 --- a/src/test/java/ac/knu/likeknu/controller/BusControllerTest.java +++ b/src/test/java/ac/knu/likeknu/controller/BusControllerTest.java @@ -4,8 +4,8 @@ import ac.knu.likeknu.controller.dto.citybus.CityBusesResponse; import ac.knu.likeknu.domain.CityBus; import ac.knu.likeknu.domain.Route; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.RouteType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.RouteType; import ac.knu.likeknu.logging.service.LoggingService; import ac.knu.likeknu.service.CityBusService; import ac.knu.likeknu.service.ShuttleBusService; diff --git a/src/test/java/ac/knu/likeknu/controller/MainControllerTest.java b/src/test/java/ac/knu/likeknu/controller/MainControllerTest.java index e743d58..9bf9216 100644 --- a/src/test/java/ac/knu/likeknu/controller/MainControllerTest.java +++ b/src/test/java/ac/knu/likeknu/controller/MainControllerTest.java @@ -1,13 +1,11 @@ package ac.knu.likeknu.controller; -import ac.knu.likeknu.controller.dto.main.MainAnnouncementsResponse; -import ac.knu.likeknu.controller.dto.main.MainCityBusResponse; -import ac.knu.likeknu.controller.dto.main.MainMenuResponse; -import ac.knu.likeknu.controller.dto.main.MainScheduleResponse; -import ac.knu.likeknu.controller.dto.menu.MenuListDto; +import ac.knu.likeknu.controller.dto.announcement.MainAnnouncementsResponse; +import ac.knu.likeknu.controller.dto.citybus.MainCityBusResponse; +import ac.knu.likeknu.controller.dto.schedule.MainScheduleResponse; import ac.knu.likeknu.domain.CityBus; import ac.knu.likeknu.domain.Route; -import ac.knu.likeknu.domain.value.Campus; +import ac.knu.likeknu.domain.constants.Campus; import ac.knu.likeknu.repository.MainHeaderMessageRepository; import ac.knu.likeknu.service.CityBusService; import ac.knu.likeknu.service.MainService; @@ -25,7 +23,6 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; import java.util.List; import static org.mockito.ArgumentMatchers.eq; @@ -143,7 +140,7 @@ void getAnnouncements() throws Exception { } - @DisplayName("캠퍼스별 식단 정보 조회 API 요청에 성공한다.") + /*@DisplayName("캠퍼스별 식단 정보 조회 API 요청에 성공한다.") @Test void getMenuResponsesAndSuccess() throws Exception { //given @@ -191,7 +188,7 @@ void getMenuResponsesAndSuccess() throws Exception { jsonPath("$.data.body.[2].menus.[1].menuName").value(menuResponse4.menus().get(1).getMenuName()) ).andDo(print()); - } + }*/ @DisplayName("학사일정 정보 조회 API 요청에 성공한다.") @Test diff --git a/src/test/java/ac/knu/likeknu/controller/MenuControllerTest.java b/src/test/java/ac/knu/likeknu/controller/MenuControllerTest.java deleted file mode 100644 index 84e0e14..0000000 --- a/src/test/java/ac/knu/likeknu/controller/MenuControllerTest.java +++ /dev/null @@ -1,161 +0,0 @@ -package ac.knu.likeknu.controller; - -import ac.knu.likeknu.controller.dto.menu.MealListDto; -import ac.knu.likeknu.controller.dto.menu.MenuListDto; -import ac.knu.likeknu.controller.dto.menu.MenuResponse; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.service.MenuService; -import ac.knu.likeknu.service.SlackService; -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.ResultActions; - -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@Slf4j -@WithMockUser -@DisplayName("메뉴 컨트롤러 테스트") -@WebMvcTest(controllers = MenuController.class) -public class MenuControllerTest { - - @Autowired - private MockMvc mockMvc; - - @MockBean - private MenuService menuService; - @MockBean - private SlackService slackService; - - @DisplayName("캠퍼스별 메뉴 상세조회 API 요청에 성공한다.") - @Test - void getMenuResponsesAndSuccess() throws Exception { - //given - LocalDate localDate = LocalDate.of(2023, 12, 11); - LocalDate localDate2 = LocalDate.of(2023, 12, 12); - - - List menuListDtos = List.of( - new MenuListDto(1, "TestMenu1"), - new MenuListDto(2, "TestMenu2"), - new MenuListDto(3, "TestMenu3") - ); - - MenuResponse menuResponse1 = new MenuResponse( - "Test1", - "TestName1", - List.of( - new MealListDto("아침", "TestTime1", new ArrayList<>(), localDate), - new MealListDto("점심", "TestTime2", menuListDtos, localDate), - new MealListDto("저녁", "TestTime3", menuListDtos, localDate) - ), - List.of( - new MealListDto("아침", "TestTime1", new ArrayList<>(), localDate), - new MealListDto("점심", "TestTime2", menuListDtos, localDate2), - new MealListDto("저녁", "TestTime3", menuListDtos, localDate2) - ) - ); - - MenuResponse menuResponse2 = new MenuResponse( - "Test2", - "TestName2", - List.of( - new MealListDto("아침", "TestTime1", new ArrayList<>(), localDate), - new MealListDto("점심", "TestTime2", new ArrayList<>(), localDate), - new MealListDto("저녁", "TestTime3", new ArrayList<>(), localDate) - ), - List.of( - new MealListDto("아침", "TestTime1", new ArrayList<>(), localDate), - new MealListDto("점심", "TestTime2", new ArrayList<>(), localDate), - new MealListDto("저녁", "TestTime3", new ArrayList<>(), localDate) - ) - ); - - MenuResponse menuResponse3 = new MenuResponse( - "Test3", - "TestName3", - List.of( - new MealListDto("아침", "TestTime3", menuListDtos, localDate), - new MealListDto("점심", "TestTime4", menuListDtos, localDate), - new MealListDto("저녁", "TestTime5", menuListDtos, localDate) - ), - List.of( - new MealListDto("아침", "TestTime3", menuListDtos, localDate2), - new MealListDto("점심", "TestTime4", menuListDtos, localDate2), - new MealListDto("저녁", "TestTime5", menuListDtos, localDate2) - ) - ); - - MenuResponse menuResponse4 = new MenuResponse( - "Test3", - "TestName3", - List.of( - new MealListDto("아침", "TestTime6", menuListDtos, localDate), - new MealListDto("점심", "TestTime7", menuListDtos, localDate), - new MealListDto("저녁", "TestTime8", menuListDtos, localDate) - ), - List.of( - new MealListDto("아침", "TestTime6", menuListDtos, localDate2), - new MealListDto("점심", "TestTime7", menuListDtos, localDate2), - new MealListDto("저녁", "TestTime8", menuListDtos, localDate2) - ) - ); - - List menuResponseList1 = List.of(menuResponse1, menuResponse2, menuResponse4); - List menuResponseList2 = List.of(menuResponse1, menuResponse3, menuResponse4); - - //when - when(menuService.getMenuResponsesByCampus(eq(Campus.CHEONAN), eq(localDate))) - .thenReturn(menuResponseList1); - when(menuService.getMenuResponsesByCampus(eq(Campus.SINGWAN), eq(localDate2))) - .thenReturn(menuResponseList2); - - ResultActions resultActions1 = mockMvc.perform( - get("/api/menu") - .param("campus", Campus.CHEONAN.name()) - .param("date", localDate.toString()) - ); - ResultActions resultActions2 = mockMvc.perform( - get("/api/menu") - .param("campus", Campus.SINGWAN.name()) - .param("date", localDate2.toString()) - ); - - //then - resultActions1.andExpectAll( - status().isOk(), - jsonPath("$.data.body.[0].cafeteriaId").value(menuResponse1.getCafeteriaId()), - jsonPath("$.data.body.[1].cafeteriaName").value(menuResponse2.getCafeteriaName()), - jsonPath("$.data.body.[2].today.[0].mealType").value(menuResponse4.getToday().get(0).getMealType()), - jsonPath("$.data.body.[2].today.[1].operatingTime").value(menuResponse4.getToday().get(1).getOperatingTime()), - jsonPath("$.data.body.[1].today.[2].menus").value(menuResponse2.getToday().get(2).getMenus()), - jsonPath("$.data.body.[2].today.[2].menus.[1].menuId").value(menuResponse4.getToday().get(2).getMenus().get(1).getMenuId()), - jsonPath("$.data.body.[2].tomorrow.[2].menus.[2].menuName").value(menuResponse4.getTomorrow().get(2).getMenus().get(2).getMenuName()) - ).andDo(print()); - - resultActions2.andExpectAll( - status().isOk(), - jsonPath("$.data.body.[0].cafeteriaId").value(menuResponse1.getCafeteriaId()), - jsonPath("$.data.body.[1].cafeteriaName").value(menuResponse3.getCafeteriaName()), - jsonPath("$.data.body.[2].today.[0].mealType").value(menuResponse4.getToday().get(0).getMealType()), - jsonPath("$.data.body.[2].tomorrow.[1].operatingTime").value(menuResponse4.getTomorrow().get(1).getOperatingTime()), - jsonPath("$.data.body.[1].today.[2].menus.[0].menuName").value(menuResponse3.getToday().get(2).getMenus().get(0).getMenuName()), - jsonPath("$.data.body.[2].tomorrow.[2].menus.[1].menuId").value(menuResponse4.getTomorrow().get(2).getMenus().get(1).getMenuId()), - jsonPath("$.data.body.[2].today.[2].menus.[2].menuName").value(menuResponse4.getToday().get(2).getMenus().get(2).getMenuName()) - ).andDo(print()); - } -} diff --git a/src/test/java/ac/knu/likeknu/service/AnnouncementServiceTest.java b/src/test/java/ac/knu/likeknu/service/AnnouncementServiceTest.java index fa5cf24..64a648b 100644 --- a/src/test/java/ac/knu/likeknu/service/AnnouncementServiceTest.java +++ b/src/test/java/ac/knu/likeknu/service/AnnouncementServiceTest.java @@ -3,9 +3,9 @@ import ac.knu.likeknu.controller.dto.announcement.AnnouncementListResponse; import ac.knu.likeknu.controller.dto.base.PageDto; import ac.knu.likeknu.domain.Announcement; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.Category; -import ac.knu.likeknu.domain.value.Tag; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.Category; +import ac.knu.likeknu.domain.constants.Tag; import ac.knu.likeknu.repository.AnnouncementRepository; import ac.knu.likeknu.utils.TestInstanceFactory; import lombok.extern.slf4j.Slf4j; diff --git a/src/test/java/ac/knu/likeknu/service/CityBusServiceTest.java b/src/test/java/ac/knu/likeknu/service/CityBusServiceTest.java index 12a8fd8..82b07f4 100644 --- a/src/test/java/ac/knu/likeknu/service/CityBusServiceTest.java +++ b/src/test/java/ac/knu/likeknu/service/CityBusServiceTest.java @@ -4,8 +4,8 @@ import ac.knu.likeknu.controller.dto.citybus.CityBusesResponse; import ac.knu.likeknu.domain.CityBus; import ac.knu.likeknu.domain.Route; -import ac.knu.likeknu.domain.value.Campus; -import ac.knu.likeknu.domain.value.RouteType; +import ac.knu.likeknu.domain.constants.Campus; +import ac.knu.likeknu.domain.constants.RouteType; import ac.knu.likeknu.repository.CityBusRepository; import ac.knu.likeknu.repository.RouteRepository; import ac.knu.likeknu.utils.TestInstanceFactory; diff --git a/src/test/java/ac/knu/likeknu/utils/TestInstanceFactory.java b/src/test/java/ac/knu/likeknu/utils/TestInstanceFactory.java index e020974..c136d7e 100644 --- a/src/test/java/ac/knu/likeknu/utils/TestInstanceFactory.java +++ b/src/test/java/ac/knu/likeknu/utils/TestInstanceFactory.java @@ -3,8 +3,8 @@ import ac.knu.likeknu.domain.Announcement; import ac.knu.likeknu.domain.CityBus; import ac.knu.likeknu.domain.Route; -import ac.knu.likeknu.domain.value.RouteType; -import ac.knu.likeknu.domain.value.Tag; +import ac.knu.likeknu.domain.constants.RouteType; +import ac.knu.likeknu.domain.constants.Tag; import java.time.LocalDate; import java.time.LocalTime;