Skip to content

Commit

Permalink
[#41] [FEATURE] 반찬의 이미지 URL을 이미지 엔티티로 분리 (#45)
Browse files Browse the repository at this point in the history
* feat: 반찬 생성, 수정 삭제 api 이미지 추가

* feat: 반찬 조회 api 이미지 추가

* refactor: 반찬 이미지 관련 코드 리팩토링

* feat: 반찬 품절여부 enum, 수량 추가

* remove: 도시락 생성 시 반찬 품절여부 검증 제거

* chore: spotless 적용
  • Loading branch information
somln authored Aug 31, 2024
1 parent 0c4fe40 commit eec3c95
Show file tree
Hide file tree
Showing 52 changed files with 778 additions and 174 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package core.startup.mealtoktok.api.dishstore;

import static core.startup.mealtoktok.api.global.util.FileMapper.toFile;

import java.util.List;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import lombok.RequiredArgsConstructor;

Expand All @@ -30,14 +34,18 @@ public class DishApi implements DishApiDocs {

private final DishService dishService;

@PostMapping(("/admin/stores/{storeId}/categories/{categoryId}/dishes"))
@PostMapping(
value = "/admin/stores/{storeId}/categories/{categoryId}/dishes",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Response<Void> createDish(
@PathVariable("storeId") Long storeId,
@PathVariable("categoryId") Long categoryId,
@RequestBody DishRequest request) {
@RequestPart MultipartFile file,
@RequestPart("request") DishRequest request) {
dishService.createDish(
TargetDishStore.from(storeId),
TargetDishCategory.from(categoryId),
toFile(file),
request.toDishInfo());
return Response.success("반찬 생성 성공");
}
Expand All @@ -49,34 +57,29 @@ public Response<Void> deleteDish(@PathVariable("dishId") Long dishId) {
}

@GetMapping("/stores/{storeId}/categories/{categoryId}/dishes")
public Response<List<DishResponse>> readDishes(
@PathVariable("storeId") Long storeId, @PathVariable("categoryId") Long categoryId) {
public Response<List<DishResponse>> readDishes(@PathVariable("categoryId") Long categoryId) {

List<DishResponse> dishResponses =
dishService
.readDishes(
TargetDishStore.from(storeId), TargetDishCategory.from(categoryId))
.stream()
dishService.readDishes(TargetDishCategory.from(categoryId)).stream()
.map(DishResponse::from)
.toList();

return Response.success(dishResponses);
}

@PatchMapping(("/admin/dishes/{dishId}"))
@PutMapping(value = "/admin/dishes/{dishId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Response<Void> updateDish(
@PathVariable("dishId") Long dishId, @RequestBody DishRequest request) {
dishService.updateDish(TargetDish.from(dishId), request.toDishInfo());
@PathVariable("dishId") Long dishId,
@RequestPart(required = false) MultipartFile file,
@RequestPart("request") DishRequest request) {
dishService.updateDish(TargetDish.from(dishId), toFile(file), request.toDishInfo());
return Response.success("반찬 수정 성공");
}

@GetMapping("/stores/{storeId}/dishes/search")
public Response<List<DishResponse>> searchDishes(
@PathVariable("storeId") Long storeId, @ModelAttribute("q") SearchDish q) {
public Response<List<DishResponse>> searchDishes(@ModelAttribute("q") SearchDish q) {
List<DishResponse> dishResponses =
dishService.searchDishes(TargetDishStore.from(storeId), q.keyword()).stream()
.map(DishResponse::from)
.toList();
dishService.searchDishes(q.keyword()).stream().map(DishResponse::from).toList();
return Response.success(dishResponses);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.List;

import org.springframework.web.multipart.MultipartFile;

import core.startup.mealtoktok.api.dishstore.request.DishRequest;
import core.startup.mealtoktok.api.dishstore.request.SearchDish;
import core.startup.mealtoktok.api.dishstore.response.DishResponse;
Expand All @@ -14,17 +16,18 @@
public interface DishApiDocs {

@Operation(summary = "반찬 생성")
Response<Void> createDish(Long storeId, Long categoryId, DishRequest request);
Response<Void> createDish(
Long storeId, Long categoryId, MultipartFile file, DishRequest request);

@Operation(summary = "반찬 삭제")
Response<Void> deleteDish(Long dishId);

@Operation(summary = "반찬 수정")
Response<Void> updateDish(Long dishId, DishRequest request);
Response<Void> updateDish(Long dishId, MultipartFile files, DishRequest request);

@Operation(summary = "반찬 리스트 조회")
Response<List<DishResponse>> readDishes(Long storeId, Long categoryId);
Response<List<DishResponse>> readDishes(Long categoryId);

@Operation(summary = "반찬 검색")
Response<List<DishResponse>> searchDishes(Long storeId, SearchDish q);
Response<List<DishResponse>> searchDishes(SearchDish q);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import core.startup.mealtoktok.domain.dishstore.DishInfo;

public record DishRequest(String dishName, int dishPrice, String imgUrl, boolean isSoldOut) {
public record DishRequest(String dishName, int dishPrice, int dishQuantity) {
public DishInfo toDishInfo() {
return DishInfo.of(dishName, dishPrice, imgUrl, isSoldOut);
return DishInfo.of(dishName, dishPrice, dishQuantity);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
package core.startup.mealtoktok.api.dishstore.response;

import core.startup.mealtoktok.common.dto.Money;
import core.startup.mealtoktok.domain.dishstore.Dish;
import core.startup.mealtoktok.domain.dishstore.DishAndImage;
import core.startup.mealtoktok.domain.dishstore.DishState;

public record DishResponse(
Long dishId, String dishName, Money dishPrice, String imgUrl, boolean isSoldOut) {
Long dishId,
String dishName,
Money dishPrice,
String imgUrl,
int dishQuantity,
DishState dishState) {

public static DishResponse from(Dish dish) {
public static DishResponse from(DishAndImage dishAndImage) {
return new DishResponse(
dish.getDishId(),
dish.getDishName(),
dish.getDishPrice(),
dish.getImgUrl(),
dish.isSoldOut());
dishAndImage.dish().getDishId(),
dishAndImage.dish().getDishName(),
dishAndImage.dish().getDishPrice(),
dishAndImage.image().getImageUrl(),
dishAndImage.dish().getDishQuantity(),
dishAndImage.dish().getDishState());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package core.startup.mealtoktok.api.global.config;

import java.lang.reflect.Type;

import org.springframework.http.MediaType;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {

public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.APPLICATION_OCTET_STREAM);
}

@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return false;
}

@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
return false;
}

@Override
protected boolean canWrite(MediaType mediaType) {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ public GroupedOpenApi dishStore() {
.build();
}

@Bean
public GroupedOpenApi meal() {
return GroupedOpenApi.builder()
.group("도시락")
.packagesToScan("core.startup.mealtoktok.api.meal")
.build();
}

@Bean
public GroupedOpenApi auth() {
return GroupedOpenApi.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,16 @@ public static List<File> toFiles(List<MultipartFile> files) {
})
.toList();
}

public static File toFile(MultipartFile file) {
if (file == null || file.isEmpty()) {
return null;
}

try {
return File.of(file.getContentType(), file.getInputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package core.startup.mealtoktok.common.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Image {

private Long id;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ public class Dish {

private Long dishId;
private String dishName;
private String imgUrl;
private Money dishPrice;
private boolean isSoldOut;
private DishState dishState;
private int dishQuantity;
private Long dishStoreId;
private Long dishCategoryId;
private DishImage dishImage;

public void addDishImage(DishImage dishImage) {
this.dishImage = dishImage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package core.startup.mealtoktok.domain.dishstore;

import core.startup.mealtoktok.common.dto.Image;

public record DishAndImage(Dish dish, Image image) {
public static DishAndImage of(Dish dish, Image images) {
return new DishAndImage(dish, images);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package core.startup.mealtoktok.domain.dishstore;

import java.util.List;

import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;

import core.startup.mealtoktok.common.dto.Image;
import core.startup.mealtoktok.domain.global.ImageReader;
import core.startup.mealtoktok.domain.global.TargetImage;

@Component
@RequiredArgsConstructor
public class DishAndImageWrapper {

private final ImageReader imageReader;

public DishAndImage wrap(Dish dish) {
Image image = imageReader.read(TargetImage.from(dish.getDishImage().imageId()));
return DishAndImage.of(dish, image);
}

public List<DishAndImage> wrapAll(List<Dish> dishes) {
return dishes.stream().map(this::wrap).toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@

import lombok.RequiredArgsConstructor;

import core.startup.mealtoktok.common.dto.Image;
import core.startup.mealtoktok.domain.global.ImageAppender;

@Component
@RequiredArgsConstructor
public class DishAppender {

private final DishValidator dishValidator;
private final DishRepository dishRepository;
private final ImageAppender imageAppender;

public void append(DishStore dishStore, DishCategory dishCategory, DishInfo dishInfo) {
public void append(
DishStore dishStore, DishCategory dishCategory, Image image, DishInfo dishInfo) {
dishValidator.validateName(dishStore, dishInfo.dishName());
dishRepository.saveDishCategory(dishStore, dishCategory, dishInfo);
Image saveImage = imageAppender.append(image);
dishRepository.saveDish(dishStore, dishCategory, dishInfo, saveImage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class DishCategoryReader {
private final DishRepository dishRepository;

public DishCategory read(TargetDishCategory targetDishCategory) {
return dishRepository.findDishById(targetDishCategory);
return dishRepository.findDishCategoryById(targetDishCategory);
}

public List<DishCategory> readAll() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@

@Service
@RequiredArgsConstructor
@Transactional
public class DishCategoryService {

private final DishCategoryReader dishCategoryReader;
private final DishCategoryRemover dishCategoryRemover;
private final DishCategoryUpdater dishCategoryUpdater;
private final DishCategoryAppender dishCategoryAppender;

@Transactional
public void createDishCategory(DishCategoryInfo dishCategoryInfo) {
dishCategoryAppender.append(dishCategoryInfo);
}
Expand All @@ -25,11 +25,13 @@ public List<DishCategory> readDishCategories() {
return dishCategoryReader.readAll();
}

@Transactional
public void deleteDishCategory(TargetDishCategory targetDishCategory) {
DishCategory dishCategory = dishCategoryReader.read(targetDishCategory);
dishCategoryRemover.remove(dishCategory);
}

@Transactional
public void updateDishCategory(
TargetDishCategory targetDishCategory, DishCategoryInfo dishCategoryInfo) {
DishCategory dishCategory = dishCategoryReader.read(targetDishCategory);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package core.startup.mealtoktok.domain.dishstore;

import lombok.Builder;

@Builder
public record DishImage(Long dishId, Long imageId) {
public static DishImage of(Long dishId, Long imageId) {
return new DishImage(dishId, imageId);
}
}
Loading

0 comments on commit eec3c95

Please sign in to comment.