Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
42ef25b
feat(Menu): isSoldOut, deleted 칼럼 및 Update, Delete 위한 메서드 추가
Jjiggu Jun 29, 2025
e45d524
feat(Menu): Update, Delete 기능 메서드 추가
Jjiggu Jun 29, 2025
512974f
feat(Menu): isSoldOut, deleted 필드 추가
Jjiggu Jun 29, 2025
db2d979
refactor(Menu): findAllByStoreId 메서드 findAllByStoreIdAndDeletedFalse로 변경
Jjiggu Jun 29, 2025
bd87e5f
feat(Menu): Update, Delete 기능 메서드 추가
Jjiggu Jun 29, 2025
3629694
refactor(Menu): findAllByStoreIdAndDeletedFalse로 변경
Jjiggu Jun 29, 2025
d1042f3
feat(Menu): Update 기능을 위한 MenuUpdateRequest Dto 추가
Jjiggu Jun 29, 2025
d644873
refactor(Store): updateInfo 메서드 수정 및 toggleActive 추가
Jjiggu Jun 29, 2025
3ad9a76
feat(Store): toggleActive 엔드포인트 추가
Jjiggu Jun 29, 2025
9c431a1
refactor(Store): 사용하지 않는 type 컬럼 삭제
Jjiggu Jun 29, 2025
6105e09
fix(Store): 변수 이름 오타 수정
Jjiggu Jun 29, 2025
8cf238b
feat(Store): toggleActive 메서드 추가
Jjiggu Jun 29, 2025
7f78d6e
refactor(Store): toggleActive 메서드 추가로 인한 isActive 필드 삭제
Jjiggu Jun 29, 2025
36eb65a
chore(Store): 어드민에서 사용하지 않는 StoreReadResponse 삭제
Jjiggu Jun 29, 2025
d0cd91f
fix(Store): 변수 오타 수정
Jjiggu Jun 29, 2025
0c020bc
refactor(Store): 필요없는 getAllStores 메서드 삭제
Jjiggu Jun 29, 2025
2f1ea46
feat(Store): getAllStoresByPage 메서드 페이지네이션 추가
Jjiggu Jun 29, 2025
3b5a026
feat(Menu): isSoldOut, deleted 필드 추가
Jjiggu Jun 29, 2025
75b11d8
refactor(Store): 사용하지 않는 type 필드 삭제
Jjiggu Jun 29, 2025
2b2a865
refactor(Store): 200 OK로 변경
Jjiggu Jun 29, 2025
6aa3d1a
fix(Store): 변수 네이밍 복수형으로 변경
Jjiggu Jun 29, 2025
0facb5e
fix(Store): 예외처리 오타 수정
Jjiggu Jun 29, 2025
f2fe047
fix(Menu): 필요없는 필드 삭제
Jjiggu Jun 29, 2025
29a9c8f
fix(Menu): toggleSoldOut HttpStatus 200 OK로 변경
Jjiggu Jun 29, 2025
5ab5121
fix(Menu): deleteMenu HttpStatus 200 OK로 변경
Jjiggu Jun 29, 2025
3991582
refactor(Menu): update 로직 soft delete 반영
Jjiggu Jun 29, 2025
d9f8c83
refactor(Menu): deleteMenu 예외처리 메시지 수정
Jjiggu Jun 29, 2025
de975c1
refactor(Menu): toggleSoldOut save 로직 추가
Jjiggu Jun 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
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;
Expand All @@ -11,6 +13,7 @@

import com.example.apiadmin.menu.dto.MenuCreateRequest;
import com.example.apiadmin.menu.dto.MenuCreateResponse;
import com.example.apiadmin.menu.dto.MenuUpdateRequest;
import com.example.apiadmin.menu.service.MenuService;
import com.nowaiting.common.api.ApiUtils;

Expand Down Expand Up @@ -43,7 +46,58 @@ public ResponseEntity<?> getMenusByStoreId(@PathVariable Long storeId) {
.status(HttpStatus.OK)
.body(
ApiUtils.success(
menuService.getMenusByStoreId(storeId)
menuService.getAllMenusByStoreId(storeId)
)
);
}

@GetMapping("/{storeId}/{menuId}")
public ResponseEntity<?> getMenuById(
@PathVariable Long storeId,
@PathVariable Long menuId
) {
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
menuService.getMenuById(storeId, menuId)
)
);
}


@PatchMapping("/update/{menuId}")
public ResponseEntity<?> updateMenu(
@PathVariable Long menuId,
@Valid @RequestBody MenuUpdateRequest request
) {
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
menuService.updateMenu(menuId, request)
)
);
}

@DeleteMapping("/delete/{menuId}")
public ResponseEntity<?> deleteMenu(@PathVariable Long menuId) {
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
menuService.deleteMenu(menuId)
)
);
}

@PatchMapping("/toggle-soldout/{menuId}")
public ResponseEntity<?> toggleSoldOut(@PathVariable Long menuId) {
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
menuService.toggleSoldOut(menuId)
)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public Menu toEntity() {
.name(name)
.description(description)
.price(price)
.isSoldOut(false)
.deleted(false)
.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class MenuCreateResponse {
private String name;
private String description;
private Integer price;
private Boolean isSoldOut;
private Boolean deleted;
private LocalDateTime createdAt;

public static MenuCreateResponse fromEntity(Menu menu) {
Expand All @@ -27,6 +29,8 @@ public static MenuCreateResponse fromEntity(Menu menu) {
.name(menu.getName())
.description(menu.getDescription())
.price(menu.getPrice())
.isSoldOut(menu.getIsSoldOut())
.deleted(menu.getDeleted())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class MenuReadDto {
private String name;
private String description;
private Integer price;
private Boolean isSoldOut;
private Boolean deleted;
private List<MenuImageUploadResponse> images;

public static MenuReadDto fromEntity(Menu menu, List<MenuImageUploadResponse> images) {
Expand All @@ -26,6 +28,8 @@ public static MenuReadDto fromEntity(Menu menu, List<MenuImageUploadResponse> im
.name(menu.getName())
.description(menu.getDescription())
.price(menu.getPrice())
.isSoldOut(menu.getIsSoldOut())
.deleted(menu.getDeleted())
.images(images)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.apiadmin.menu.dto;

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

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class MenuUpdateRequest {
private String name;
private String description;
private Integer price;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.example.apiadmin.menu.dto.MenuImageUploadResponse;
import com.example.apiadmin.menu.dto.MenuReadDto;
import com.example.apiadmin.menu.dto.MenuReadResponse;
import com.example.apiadmin.menu.dto.MenuUpdateRequest;
import com.example.menu.entity.Menu;
import com.example.menu.entity.MenuImage;
import com.example.menu.repository.MenuImageRepository;
Expand All @@ -34,10 +35,10 @@ public MenuCreateResponse createMenu(MenuCreateRequest request) {
}

@Transactional(readOnly = true)
public MenuReadResponse getMenusByStoreId(Long storeId) {
List<Menu> menus = menuRepository.findAllByStoreId(storeId);
public MenuReadResponse getAllMenusByStoreId(Long storeId) {
List<Menu> menus = menuRepository.findAllByStoreIdAndDeletedFalse(storeId);

List<MenuReadDto> menuReadRespons = menus.stream()
List<MenuReadDto> menuReadResponse = menus.stream()
.map(menu -> {
List<MenuImage> images = menuImageRepository.findByMenu(menu);
List<MenuImageUploadResponse> imageDto = images.stream()
Expand All @@ -47,6 +48,63 @@ public MenuReadResponse getMenusByStoreId(Long storeId) {
})
.toList();

return MenuReadResponse.of(menuReadRespons);
return MenuReadResponse.of(menuReadResponse);
}

@Transactional(readOnly = true)
public MenuReadDto getMenuById(Long storeId, Long menuId) {
Menu menu = menuRepository.findByStoreIdAndIdAndDeletedFalse(storeId, menuId)
.orElseThrow(() -> new IllegalArgumentException("Menu not found with id: " + menuId));

List<MenuImage> images = menuImageRepository.findByMenu(menu);
List<MenuImageUploadResponse> imageDto = images.stream()
.map(MenuImageUploadResponse::fromEntity)
.toList();

return MenuReadDto.fromEntity(menu, imageDto);
}


@Transactional
public MenuReadDto updateMenu(Long menuId, MenuUpdateRequest request) {
Menu menu = menuRepository.findByIdAndDeletedFalse(menuId)
.orElseThrow(() -> new IllegalArgumentException("Menu not found with id: " + menuId));

menu.updateInfo(
request.getName(),
request.getDescription(),
request.getPrice()
);

Menu saved = menuRepository.save(menu);

List<MenuImage> images = menuImageRepository.findByMenu(saved);
List<MenuImageUploadResponse> imageDto = images.stream()
.map(MenuImageUploadResponse::fromEntity)
.toList();

return MenuReadDto.fromEntity(saved, imageDto);
}

@Transactional
public String deleteMenu(Long menuId) {
Menu menu = menuRepository.findById(menuId)
.orElseThrow(() -> new IllegalArgumentException("Menu is already deleted with id: " + menuId));

menu.markAsDeleted();
menuRepository.save(menu);

return "Menu with ID " + menuId + " 삭제되었습니다.";
}

@Transactional
public Boolean toggleSoldOut(Long menuId) {
Menu menu = menuRepository.findById(menuId)
.orElseThrow(() -> new IllegalArgumentException("해당 메뉴가 존재하지 않습니다."));

menu.toggleSoldOut();
menuRepository.save(menu);
return menu.getIsSoldOut();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,6 @@ public ResponseEntity<?> createStore(@Valid @RequestBody StoreCreateRequest requ
);
}

@GetMapping("/all-stores")
public ResponseEntity<?> getAllStores() {
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
storeService.getAllStores()
)
);
}

@GetMapping("/{storeId}")
public ResponseEntity<?> getStoreById(@PathVariable Long storeId) {
return ResponseEntity
Expand Down Expand Up @@ -86,4 +75,15 @@ public ResponseEntity<?> deleteStore(@PathVariable Long storeId) {
)
);
}

@PatchMapping("/toggle-active/{storeId}")
public ResponseEntity<?> toggleActive(@PathVariable Long storeId) {
return ResponseEntity
.status(HttpStatus.OK)
.body(
ApiUtils.success(
storeService.toggleActive(storeId)
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ public class StoreImageController {
@PostMapping("/store-images/{storeId}")
public ResponseEntity<?> uploadStoreImage(
@PathVariable Long storeId,
@RequestParam("files") List<MultipartFile> files,
@RequestParam(value = "types") List<String> types
@RequestParam("files") List<MultipartFile> files
) {
// TODO 관련 정책 확정되면 메서드로 분리 예정
// 파일 개수 제한 검증
Expand All @@ -46,7 +45,7 @@ public ResponseEntity<?> uploadStoreImage(
}
}

List<StoreImageUploadResponse> response = storeImageService.saveAll(storeId, files, types);
List<StoreImageUploadResponse> response = storeImageService.saveAll(storeId, files);
return ResponseEntity
.status(HttpStatus.CREATED)
.body(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@
public class StoreImageUploadResponse {
private final Long id;
private final String imageUrl;
private final String type;

public static StoreImageUploadResponse fromEntity(StoreImage storeImage) {
return StoreImageUploadResponse.builder()
.id(storeImage.getId())
.imageUrl(storeImage.getImageUrl())
.type(storeImage.getType())
.build();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,4 @@ public class StoreUpdateRequest {
private String name;
private String location;
private String description;
private Boolean isActive;
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ public class StoreImageService {
private final S3Service s3Service;

@Transactional
public List<StoreImageUploadResponse> saveAll(Long storeId, List<MultipartFile> files, List<String> types) {
if (files.size() != types.size()) {
throw new IllegalArgumentException("파일과 타입의 개수가 일치해야 합니다.");
}
public List<StoreImageUploadResponse> saveAll(Long storeId, List<MultipartFile> files) {

String type = "store";
Store store = storeRepository.findById(storeId)
Expand Down Expand Up @@ -61,7 +58,6 @@ public List<StoreImageUploadResponse> saveAll(Long storeId, List<MultipartFile>
.store(store)
.imageUrl(uploadResult.url())
.fileKey(uploadResult.key())
.type(types.get(i))
.build();

storeImageRepository.save(storeImage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
import com.example.apiadmin.store.dto.StoreCreateRequest;
import com.example.apiadmin.store.dto.StoreCreateResponse;
import com.example.apiadmin.store.dto.StoreReadDto;
import com.example.apiadmin.store.dto.StoreReadResponse;
import com.example.apiadmin.store.dto.StoreUpdateRequest;

public interface StoreService {

StoreCreateResponse createStore(StoreCreateRequest request);

StoreReadResponse getAllStores();

StoreReadDto getStoreByStoreId(Long storeId);

StoreReadDto updateStore(Long storeId, StoreUpdateRequest request);

String deleteStore(Long storeId);

Boolean toggleActive(Long storeId);
}
Loading