From 4ea06564d70f9f9bab4bc56fa47214b9875d7275 Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 18:32:03 +0900 Subject: [PATCH 1/9] =?UTF-8?q?[FEAT]:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20API?= =?UTF-8?q?=20=EB=B0=8F=20=EB=AA=85=EC=84=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/StoreTableController.java | 15 ++++++++ .../controller/StoreTableControllerDocs.java | 34 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java index 0b26953..085c660 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java @@ -5,12 +5,15 @@ import com.eatsfine.eatsfine.domain.storetable.exception.status.StoreTableSuccessStatus; import com.eatsfine.eatsfine.domain.storetable.service.StoreTableCommandService; import com.eatsfine.eatsfine.domain.storetable.service.StoreTableQueryService; +import com.eatsfine.eatsfine.domain.tableimage.status.TableImageSuccessStatus; import com.eatsfine.eatsfine.global.apiPayload.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; @@ -66,4 +69,16 @@ public ApiResponse deleteTable( ) { return ApiResponse.of(StoreTableSuccessStatus._TABLE_DELETED, storeTableCommandService.deleteTable(storeId, tableId)); } + + @PostMapping( + value = "/stores/{storeId}/tables/{tableId}/table-image", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE + ) + public ApiResponse uploadTableImage( + @PathVariable Long storeId, + @PathVariable Long tableId, + @RequestPart("tableImage") MultipartFile tableImage + ) { + return ApiResponse.of(TableImageSuccessStatus._STORE_TABLE_IMAGE_UPLOAD_SUCCESS, storeTableCommandService.uploadTableImage(storeId, tableId, tableImage)); + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java index fc4ce97..b689eb7 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java @@ -5,11 +5,14 @@ import com.eatsfine.eatsfine.global.apiPayload.ApiResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; @@ -187,4 +190,35 @@ ApiResponse deleteTable( @Parameter(description = "테이블 ID", required = true, example = "1") Long tableId ); + + @Operation( + summary = "테이블 이미지 등록", + description = """ + 특정 테이블의 이미지를 등록합니다. + + - 테이블당 1개의 이미지만 등록 가능합니다. + - 기존 이미지가 있는 경우 자동으로 삭제되고 새 이미지로 교체됩니다. + - S3 저장 경로: stores/{storeId}/tables/{tableId}/ + """ + ) + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "테이블 이미지 등록 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 요청 (빈 파일, 지원하지 않는 파일 형식 등)"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "가게 또는 테이블을 찾을 수 없음"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "500", description = "S3 업로드 실패") + }) + ApiResponse uploadTableImage( + @Parameter(description = "가게 ID", required = true, example = "1") + Long storeId, + + @Parameter(description = "테이블 ID", required = true, example = "1") + Long tableId, + + @Parameter( + description = "업로드할 테이블 이미지 파일", + required = true, + content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE) + ) + MultipartFile tableImage + ); } From 68419bbca81aadf5edbadb6d8847b245769839e5 Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 18:34:28 +0900 Subject: [PATCH 2/9] =?UTF-8?q?[FEAT]:=20StoreTable=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eatsfine/domain/storetable/entity/StoreTable.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java index ec01cf2..95f9e13 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java @@ -85,4 +85,9 @@ public void updateSeatCount(int minSeatCount, int maxSeatCount) { public void updateSeatsType(SeatsType seatsType) { this.seatsType = seatsType; } + + // 테이블 이미지 업로드 + public void updateTableImage(String imageKey) { + this.tableImageUrl = imageKey; + } } From 11bdf6ae123099ab7e390144d59d04a9f25ccbe8 Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 19:32:52 +0900 Subject: [PATCH 3/9] =?UTF-8?q?[FEAT]:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20DTO,=20Converter=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/storetable/converter/StoreTableConverter.java | 7 +++++++ .../domain/storetable/dto/res/StoreTableResDto.java | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java index 4ef71d7..c23c8a4 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java @@ -94,4 +94,11 @@ public static StoreTableResDto.TableDeleteDto toTableDeleteDto(StoreTable table) .tableId(table.getId()) .build(); } + + public static StoreTableResDto.UploadTableImageDto toUploadTableImageDto(Long tableId, String tableImageUrl) { + return StoreTableResDto.UploadTableImageDto.builder() + .tableId(tableId) + .tableImageUrl(tableImageUrl) + .build(); + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java index 1472a7f..3c9b3d0 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java @@ -82,4 +82,10 @@ public record UpdatedTableDto( public record TableDeleteDto( Long tableId ) {} + + @Builder + public record UploadTableImageDto( + Long tableId, + String tableImageUrl + ) {} } From 9c1adcfe718b86752985ffc53059fee05016cae5 Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 19:33:14 +0900 Subject: [PATCH 4/9] =?UTF-8?q?[FEAT]:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/StoreTableCommandService.java | 3 ++ .../service/StoreTableCommandServiceImpl.java | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java index 515b791..cc95bc9 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java @@ -2,6 +2,7 @@ import com.eatsfine.eatsfine.domain.storetable.dto.req.StoreTableReqDto; import com.eatsfine.eatsfine.domain.storetable.dto.res.StoreTableResDto; +import org.springframework.web.multipart.MultipartFile; public interface StoreTableCommandService { StoreTableResDto.TableCreateDto createTable(Long storeId, StoreTableReqDto.TableCreateDto dto); @@ -9,4 +10,6 @@ public interface StoreTableCommandService { StoreTableResDto.TableUpdateResultDto updateTable(Long storeId, Long tableId, StoreTableReqDto.TableUpdateDto dto); StoreTableResDto.TableDeleteDto deleteTable(Long storeId, Long tableId); + + StoreTableResDto.UploadTableImageDto uploadTableImage(Long storeId, Long tableId, MultipartFile tableImage); } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java index 12c6b77..1c00cc4 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java @@ -1,6 +1,8 @@ package com.eatsfine.eatsfine.domain.storetable.service; import com.eatsfine.eatsfine.domain.booking.repository.BookingRepository; +import com.eatsfine.eatsfine.domain.image.exception.ImageException; +import com.eatsfine.eatsfine.domain.image.status.ImageErrorStatus; import com.eatsfine.eatsfine.domain.store.exception.StoreException; import com.eatsfine.eatsfine.domain.store.repository.StoreRepository; import com.eatsfine.eatsfine.domain.store.status.StoreErrorStatus; @@ -16,9 +18,11 @@ import com.eatsfine.eatsfine.domain.table_layout.exception.TableLayoutException; import com.eatsfine.eatsfine.domain.table_layout.exception.status.TableLayoutErrorStatus; import com.eatsfine.eatsfine.domain.table_layout.repository.TableLayoutRepository; +import com.eatsfine.eatsfine.global.s3.S3Service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import java.math.BigDecimal; import java.time.LocalDate; @@ -35,6 +39,7 @@ public class StoreTableCommandServiceImpl implements StoreTableCommandService { private final TableLayoutRepository tableLayoutRepository; private final StoreTableRepository storeTableRepository; private final BookingRepository bookingRepository; + private final S3Service s3Service; // 테이블 생성 @Override @@ -160,6 +165,36 @@ public StoreTableResDto.TableDeleteDto deleteTable(Long storeId, Long tableId) { return StoreTableConverter.toTableDeleteDto(table); } + // 테이블 이미지 업로드 + @Override + public StoreTableResDto.UploadTableImageDto uploadTableImage(Long storeId, Long tableId, MultipartFile tableImage) { + storeRepository.findById(storeId) + .orElseThrow(() -> new StoreException(StoreErrorStatus._STORE_NOT_FOUND)); + + StoreTable table = storeTableRepository.findById(tableId) + .orElseThrow(() -> new StoreTableException(StoreTableErrorStatus._TABLE_NOT_FOUND)); + + StoreTableValidator.validateTableBelongsToStore(table, storeId); + + if (tableImage == null || tableImage.isEmpty()) { + throw new ImageException(ImageErrorStatus.EMPTY_FILE); + } + + // 기존 이미지가 존재할 경우 삭제 + if (table.getTableImageUrl() != null && !table.getTableImageUrl().isBlank()) { + s3Service.deleteByKey(table.getTableImageUrl()); + } + + String key = s3Service.upload(tableImage, "stores/" + storeId + "/tables/" + tableId); + + table.updateTableImage(key); + + // URL 변환 및 응답 + String tableImageUrl = s3Service.toUrl(key); + + return StoreTableConverter.toUploadTableImageDto(tableId, tableImageUrl); + } + private String generateTableNumber(TableLayout layout) { List tables = layout.getTables(); From 05fb60dbaa965d51b55955f4ab4a593199992440 Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 19:34:24 +0900 Subject: [PATCH 5/9] =?UTF-8?q?[REFACTOR]:=20=ED=85=8C=EC=9D=B4=EB=B8=94?= =?UTF-8?q?=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20URL?= =?UTF-8?q?=EC=9D=84=20=ED=8F=AC=ED=95=A8=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/storetable/converter/StoreTableConverter.java | 4 ++-- .../storetable/service/StoreTableQueryServiceImpl.java | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java index c23c8a4..54740b3 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java @@ -43,12 +43,12 @@ public static StoreTableResDto.SlotListDto toSlotListDto(int totalCount, int ava .build(); } - public static StoreTableResDto.TableDetailDto toTableDetailDto(StoreTable table, LocalDate targetDate, int totalSlotCount, int availableSlotCount) { + public static StoreTableResDto.TableDetailDto toTableDetailDto(StoreTable table, LocalDate targetDate, int totalSlotCount, int availableSlotCount, String tableImageUrl) { return StoreTableResDto.TableDetailDto.builder() .tableId(table.getId()) .minSeatCount(table.getMinSeatCount()) .maxSeatCount(table.getMaxSeatCount()) - .tableImageUrl(table.getTableImageUrl()) + .tableImageUrl(tableImageUrl) .rating(table.getRating()) .reviewCount(0) // 리뷰 기능 미구현으로 0 반환 .seatsType(table.getSeatsType()) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableQueryServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableQueryServiceImpl.java index d2690dd..99e262b 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableQueryServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableQueryServiceImpl.java @@ -14,6 +14,7 @@ import com.eatsfine.eatsfine.domain.storetable.validator.StoreTableValidator; import com.eatsfine.eatsfine.domain.tableblock.entity.TableBlock; import com.eatsfine.eatsfine.domain.tableblock.repository.TableBlockRepository; +import com.eatsfine.eatsfine.global.s3.S3Service; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,6 +33,7 @@ public class StoreTableQueryServiceImpl implements StoreTableQueryService{ private final StoreTableRepository storeTableRepository; private final TableBlockRepository tableBlockRepository; private final BookingRepository bookingRepository; + private final S3Service s3Service; // 테이블 슬롯 조회 @Override @@ -57,6 +59,7 @@ public StoreTableResDto.SlotListDto getTableSlots(Long storeId, Long tableId, Lo ); } + // 테이블 상세 조회 @Override public StoreTableResDto.TableDetailDto getTableDetail(Long storeId, Long tableId, LocalDate targetDate) { storeRepository.findById(storeId) @@ -73,11 +76,15 @@ public StoreTableResDto.TableDetailDto getTableDetail(Long storeId, Long tableId SlotCalculator.SlotCalculationResult result = SlotCalculator.calculateSlots(storeTable, targetDate, tableBlocks, bookedTimes); + // S3 Key -> Url 변환 + String tableImageUrl = s3Service.toUrl(storeTable.getTableImageUrl()); + return StoreTableConverter.toTableDetailDto( storeTable, targetDate, result.totalSlotCount(), - result.availableSlotCount() + result.availableSlotCount(), + tableImageUrl ); } } From be457ce762f4d2dd67a14dd94b35619a13ae32a2 Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 20:16:02 +0900 Subject: [PATCH 6/9] =?UTF-8?q?[FEAT]:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=82=AD=EC=A0=9C=20API=20?= =?UTF-8?q?=EB=B0=8F=20=EB=AA=85=EC=84=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/StoreTableController.java | 8 +++++++ .../controller/StoreTableControllerDocs.java | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java index 085c660..64835ec 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableController.java @@ -81,4 +81,12 @@ public ApiResponse uploadTableImage( ) { return ApiResponse.of(TableImageSuccessStatus._STORE_TABLE_IMAGE_UPLOAD_SUCCESS, storeTableCommandService.uploadTableImage(storeId, tableId, tableImage)); } + + @DeleteMapping("/stores/{storeId}/tables/{tableId}/table-image") + public ApiResponse deleteTableImage( + @PathVariable Long storeId, + @PathVariable Long tableId + ) { + return ApiResponse.of(TableImageSuccessStatus._STORE_TABLE_IMAGE_DELETE_SUCCESS, storeTableCommandService.deleteTableImage(storeId, tableId)); + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java index b689eb7..8e682ef 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/controller/StoreTableControllerDocs.java @@ -221,4 +221,27 @@ ApiResponse uploadTableImage( ) MultipartFile tableImage ); + + @Operation( + summary = "테이블 이미지 삭제", + description = """ + 특정 테이블의 이미지를 삭제합니다. + + - 등록된 이미지가 없는 경우 404 에러가 발생합니다. + - S3에서 이미지가 삭제되고, DB의 이미지 URL도 null로 업데이트됩니다. + - 삭제 후 다시 이미지를 등록할 수 있습니다. + """ + ) + @ApiResponses({ + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "테이블 이미지 삭제 성공"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "테이블이 해당 가게에 속하지 않음"), + @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "가게, 테이블을 찾을 수 없거나 이미지가 등록되지 않음") + }) + ApiResponse deleteTableImage( + @Parameter(description = "가게 ID", required = true, example = "1") + Long storeId, + + @Parameter(description = "테이블 ID", required = true, example = "1") + Long tableId + ); } From 62062b78e26af80d73a50db75304145ee308f75f Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 20:19:03 +0900 Subject: [PATCH 7/9] =?UTF-8?q?[FEAT]:=20StoreTable=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eatsfine/domain/storetable/entity/StoreTable.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java index 95f9e13..0de743c 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/entity/StoreTable.java @@ -90,4 +90,9 @@ public void updateSeatsType(SeatsType seatsType) { public void updateTableImage(String imageKey) { this.tableImageUrl = imageKey; } + + // 테이블 이미지 삭제 + public void deleteTableImage() { + this.tableImageUrl = null; + } } From 4f846bd47d069d40be420a175f4405cb7a6e0c39 Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 20:19:25 +0900 Subject: [PATCH 8/9] =?UTF-8?q?[FEAT]:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=82=AD=EC=A0=9C=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20DTO,=20Converter=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/storetable/converter/StoreTableConverter.java | 6 ++++++ .../domain/storetable/dto/res/StoreTableResDto.java | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java index 54740b3..98619e0 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/converter/StoreTableConverter.java @@ -101,4 +101,10 @@ public static StoreTableResDto.UploadTableImageDto toUploadTableImageDto(Long ta .tableImageUrl(tableImageUrl) .build(); } + + public static StoreTableResDto.DeleteTableImageDto toDeleteTableImageDto(Long tableId) { + return StoreTableResDto.DeleteTableImageDto.builder() + .tableId(tableId) + .build(); + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java index 3c9b3d0..cf04854 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/dto/res/StoreTableResDto.java @@ -88,4 +88,9 @@ public record UploadTableImageDto( Long tableId, String tableImageUrl ) {} + + @Builder + public record DeleteTableImageDto( + Long tableId + ) {} } From df04007f3311f902c0c40ea3d41576d2997030ff Mon Sep 17 00:00:00 2001 From: sonjunkyu Date: Wed, 28 Jan 2026 20:19:39 +0900 Subject: [PATCH 9/9] =?UTF-8?q?[FEAT]:=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=82=AD=EC=A0=9C=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/StoreTableCommandService.java | 2 ++ .../service/StoreTableCommandServiceImpl.java | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java index cc95bc9..2f3d8ad 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandService.java @@ -12,4 +12,6 @@ public interface StoreTableCommandService { StoreTableResDto.TableDeleteDto deleteTable(Long storeId, Long tableId); StoreTableResDto.UploadTableImageDto uploadTableImage(Long storeId, Long tableId, MultipartFile tableImage); + + StoreTableResDto.DeleteTableImageDto deleteTableImage(Long storeId, Long tableId); } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java index 1c00cc4..6117500 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/storetable/service/StoreTableCommandServiceImpl.java @@ -195,6 +195,28 @@ public StoreTableResDto.UploadTableImageDto uploadTableImage(Long storeId, Long return StoreTableConverter.toUploadTableImageDto(tableId, tableImageUrl); } + @Override + public StoreTableResDto.DeleteTableImageDto deleteTableImage(Long storeId, Long tableId) { + storeRepository.findById(storeId) + .orElseThrow(() -> new StoreException(StoreErrorStatus._STORE_NOT_FOUND)); + + StoreTable table = storeTableRepository.findById(tableId) + .orElseThrow(() -> new StoreTableException(StoreTableErrorStatus._TABLE_NOT_FOUND)); + + StoreTableValidator.validateTableBelongsToStore(table, storeId); + + // 이미지가 존재하는지 확인 + if (table.getTableImageUrl() == null || table.getTableImageUrl().isBlank()) { + throw new ImageException(ImageErrorStatus._IMAGE_NOT_FOUND); + } + + s3Service.deleteByKey(table.getTableImageUrl()); + + table.deleteTableImage(); + + return StoreTableConverter.toDeleteTableImageDto(tableId); + } + private String generateTableNumber(TableLayout layout) { List tables = layout.getTables();