From b73e7bcc3cc923bcbd5c29e455dab0edda9faafd Mon Sep 17 00:00:00 2001 From: twodo0 Date: Thu, 15 Jan 2026 17:49:16 +0900 Subject: [PATCH 01/14] =?UTF-8?q?[FEAT]:=20=EA=B0=80=EA=B2=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20DTO=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/store/dto/StoreReqDto.java | 26 +++++++++++++++++++ .../domain/store/dto/StoreResDto.java | 7 +++++ 2 files changed, 33 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreReqDto.java b/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreReqDto.java index 3e7ff19..7330116 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreReqDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreReqDto.java @@ -6,6 +6,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.Builder; import java.util.List; @@ -29,6 +30,10 @@ public record StoreCreateDto( @NotBlank(message = "주소는 필수입니다.") String address, + @Pattern( + regexp = "^0\\d{1,2}-\\d{3,4}-\\d{4}$", + message = "전화번호 형식이 올바르지 않습니다." + ) @NotBlank(message = "전화번호는 필수입니다.") String phoneNumber, @@ -46,4 +51,25 @@ public record StoreCreateDto( @Valid List businessHours ){} + + @Builder + public record StoreUpdateDto( + String storeName, + + String description, + + @Pattern( + regexp = "^0\\d{1,2}-\\d{3,4}-\\d{4}$", + message = "전화번호 형식이 올바르지 않습니다. (예: 02-123-4567, 010-1234-5678)" + ) + String phoneNumber, + + Category category, + + Integer minPrice, + + DepositRate depositRate, + + Integer bookingIntervalMinutes + ){} } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java b/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java index 7cd66f6..ca3fcee 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java @@ -65,4 +65,11 @@ public record uploadMainImageResDto( String mainImageUrl ) {} + // 식당 수정 응답 + @Builder + public record StoreUpdateDto( + Long storeId, + List updatedFields + ){}; + } From b78c558ad9feec26010da0efb0070bfe85c0bf14 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Thu, 15 Jan 2026 18:02:03 +0900 Subject: [PATCH 02/14] =?UTF-8?q?[FEAT]:=20StoreSuccessStatus=EC=97=90=20?= =?UTF-8?q?=EA=B0=80=EA=B2=8C=20=EA=B8=B0=EB=B3=B8=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=84=B1=EA=B3=B5=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eatsfine/domain/store/status/StoreSuccessStatus.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/status/StoreSuccessStatus.java b/src/main/java/com/eatsfine/eatsfine/domain/store/status/StoreSuccessStatus.java index 067ef69..088f093 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/status/StoreSuccessStatus.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/status/StoreSuccessStatus.java @@ -14,9 +14,11 @@ public enum StoreSuccessStatus implements BaseCode { _STORE_SEARCH_SUCCESS(HttpStatus.OK, "STORE2002", "성공적으로 가게를 검색했습니다."), - _STORE_DETAIL_FOUND(HttpStatus.FOUND, "STORE_DETAIL200", "성공적으로 가게 상세 리뷰를 조회했습니다."), + _STORE_DETAIL_FOUND(HttpStatus.OK, "STORE2003", "성공적으로 가게 상세 리뷰를 조회했습니다."), - _STORE_CREATED(HttpStatus.CREATED, "STORE201", "성공적으로 가게를 등록했습니다.") + _STORE_CREATED(HttpStatus.CREATED, "STORE201", "성공적으로 가게를 등록했습니다."), + + _STORE_UPDATE_SUCCESS(HttpStatus.OK, "STORE2004", "성공적으로 가게 기본 정보를 수정했습니다.") ; From 4bd00558e19e46f3c4b847729c37989df92d12c1 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Thu, 15 Jan 2026 18:02:37 +0900 Subject: [PATCH 03/14] =?UTF-8?q?[FEAT]:=20Store=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=EC=97=90=20=EA=B0=80=EA=B2=8C=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EB=A9=94=EC=84=9C?= =?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/store/entity/Store.java | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java b/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java index 3717efd..e555565 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java @@ -2,6 +2,7 @@ import com.eatsfine.eatsfine.domain.businesshours.entity.BusinessHours; import com.eatsfine.eatsfine.domain.region.entity.Region; +import com.eatsfine.eatsfine.domain.store.dto.StoreReqDto; import com.eatsfine.eatsfine.domain.store.enums.Category; import com.eatsfine.eatsfine.domain.store.enums.DepositRate; import com.eatsfine.eatsfine.domain.table_layout.entity.TableLayout; @@ -92,8 +93,6 @@ public class Store extends BaseEntity { private List tableImages = new ArrayList<>(); // StoreTable이 아닌 TableLayout 엔티티 참조 -// @OneToMany(mappedBy = "store") -// private List storeTables = new ArrayList<>(); @Builder.Default @OneToMany(mappedBy = "store") @@ -143,4 +142,35 @@ public BigDecimal calculateDepositAmount() { // StoreTable에 대한 연관관계 편의 메서드는 추후 추가 예정 + // 가게 기본 정보 변경 메서드 + public void updateBasicInfo(StoreReqDto.StoreUpdateDto dto) { + if(dto.storeName() != null) { + this.storeName = dto.storeName(); + } + + if(dto.description() != null) { + this.description = dto.description(); + } + + if(dto.phoneNumber() != null) { + this.phoneNumber = dto.phoneNumber(); + } + + if(dto.category() != null) { + this.category = dto.category(); + } + + if(dto.minPrice() != null) { + this.minPrice = dto.minPrice(); + } + + if(dto.depositRate() != null) { + this.depositRate = dto.depositRate(); + } + + if(dto.bookingIntervalMinutes() != null) { + this.bookingIntervalMinutes = dto.bookingIntervalMinutes(); + } + } + } From 1d322ad3ef9f81ac054aae59a69329cca37af961 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Thu, 15 Jan 2026 18:05:37 +0900 Subject: [PATCH 04/14] =?UTF-8?q?[FEAT]:=20=EA=B0=80=EA=B2=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=A0=95=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/converter/StoreConverter.java | 8 +++++ .../store/service/StoreCommandService.java | 1 + .../service/StoreCommandServiceImpl.java | 33 ++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java index 759aac6..85fd44e 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java @@ -6,6 +6,7 @@ import java.math.BigDecimal; import java.util.Collections; +import java.util.List; public class StoreConverter { @@ -49,5 +50,12 @@ public static StoreResDto.StoreDetailDto toDetailDto(Store store, boolean isOpen .isOpenNow(isOpenNow) // 추후 영업 여부 판단 로직 구현 예정 .build(); } + + public static StoreResDto.StoreUpdateDto toUpdateDto(Long storeId, List updatedFields) { + return StoreResDto.StoreUpdateDto.builder() + .storeId(storeId) + .updatedFields(updatedFields) + .build(); } +} diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandService.java b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandService.java index f79fe42..65ab017 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandService.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandService.java @@ -5,4 +5,5 @@ public interface StoreCommandService { StoreResDto.StoreCreateDto createStore(StoreReqDto.StoreCreateDto storeCreateDto); + StoreResDto.StoreUpdateDto updateBasicInfo(Long storeId, StoreReqDto.StoreUpdateDto storeUpdateDto); } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java index f843fb6..dcd3e91 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java @@ -12,9 +12,13 @@ import com.eatsfine.eatsfine.domain.store.entity.Store; import com.eatsfine.eatsfine.domain.store.exception.StoreException; import com.eatsfine.eatsfine.domain.store.repository.StoreRepository; -import jakarta.transaction.Transactional; +import com.eatsfine.eatsfine.domain.store.status.StoreErrorStatus; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; @Service @Transactional @@ -57,4 +61,31 @@ public StoreResDto.StoreCreateDto createStore(StoreReqDto.StoreCreateDto dto) { return StoreConverter.toCreateDto(savedStore); } + // 가게 기본 정보 수정 (필드) + @Override + public StoreResDto.StoreUpdateDto updateBasicInfo(Long storeId, StoreReqDto.StoreUpdateDto dto) { + Store store = storeRepository.findById(storeId) + .orElseThrow(() -> new StoreException(StoreErrorStatus._STORE_NOT_FOUND)); + + store.updateBasicInfo(dto); + List updatedFields = extractUpdatedFields(dto); + + return StoreConverter.toUpdateDto(storeId, updatedFields); + } + + // 수정된 필드 목록 + public List extractUpdatedFields(StoreReqDto.StoreUpdateDto dto) { + List updated = new ArrayList<>(); + + if(dto.storeName() != null) updated.add("storeName"); + if(dto.description() != null) updated.add("description"); + if(dto.phoneNumber() != null) updated.add("phoneNumber"); + if(dto.category() != null) updated.add("category"); + if(dto.minPrice() != null) updated.add("minPrice"); + if(dto.depositRate() != null) updated.add("depositRate"); + if(dto.bookingIntervalMinutes() != null) updated.add("bookingIntervalMinutes"); + + return updated; + } + } \ No newline at end of file From 94108b6694d06e0ac91503a83c74b8e8ebc2e795 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Thu, 15 Jan 2026 18:13:24 +0900 Subject: [PATCH 05/14] =?UTF-8?q?[FEAT]:=20StoreController=EC=97=90=20?= =?UTF-8?q?=EA=B0=80=EA=B2=8C=20=EA=B8=B0=EB=B3=B8=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/store/controller/StoreController.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java b/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java index c207c4b..209cbdf 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java @@ -57,4 +57,18 @@ public ApiResponse getStoreDetail(@PathVariable Long return ApiResponse.of(StoreSuccessStatus._STORE_DETAIL_FOUND, storeQueryService.getStoreDetail(storeId)); } + @Operation( + summary = "가게 기본 정보 수정", + description = "가게 기본 정보(단일 필드)를 수정합니다. " + + "영업시간, 브레이크타임, 이미지는 별도 엔티티/컬렉션이므로 개별 API로 분리" + ) + @PatchMapping("/stores/{storeId}") + public ApiResponse updateStoreBasicInfo( + @PathVariable Long storeId, + @Valid @RequestBody StoreReqDto.StoreUpdateDto dto + ) { + return ApiResponse.of(StoreSuccessStatus._STORE_UPDATE_SUCCESS, storeCommandService.updateBasicInfo(storeId, dto)); + } + + } From 6527ae7aadc0a537faa14af5ae75c1ec0d0a7fcc Mon Sep 17 00:00:00 2001 From: twodo0 Date: Thu, 15 Jan 2026 23:26:44 +0900 Subject: [PATCH 06/14] =?UTF-8?q?[FEAT]:=20=EC=98=81=EC=97=85=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EA=B2=80=EC=A6=9D=20=EB=A9=94=EC=84=9C=EB=93=9C(?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9A=A9/=EC=88=98=EC=A0=95=EC=9A=A9)=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../businesshours/validator/BusinessHoursValidator.java | 9 +++++++-- .../domain/store/service/StoreCommandServiceImpl.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java index f173851..b9bc7dc 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java @@ -10,15 +10,20 @@ import java.util.Set; public class BusinessHoursValidator { - public static void validate(List dto) { + public static void validateForCreate(List dto) { validateComplete(dto); validateDuplicateDayOfWeek(dto); validateOpenDay(dto); validateClosedDay(dto); validateOpenCloseTime(dto); + } - + public static void validateForUpdate(List dto) { + validateDuplicateDayOfWeek(dto); + validateOpenDay(dto); + validateClosedDay(dto); + validateOpenCloseTime(dto); } // 7일 모두 입력 여부 검증 diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java index dcd3e91..982f0be 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreCommandServiceImpl.java @@ -34,7 +34,7 @@ public StoreResDto.StoreCreateDto createStore(StoreReqDto.StoreCreateDto dto) { .orElseThrow(() -> new StoreException(RegionErrorStatus._REGION_NOT_FOUND)); // 영업시간 정상 여부 검증 - BusinessHoursValidator.validate(dto.businessHours()); + BusinessHoursValidator.validateForCreate(dto.businessHours()); Store store = Store.builder() .owner(null) // User 도메인 머지 후 owner 처리 예정 From 5abb4809cc7f7d1f3ac8ef754d3c887f94f58dd9 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Thu, 15 Jan 2026 23:34:21 +0900 Subject: [PATCH 07/14] =?UTF-8?q?[FEAT]:=20=EC=98=81=EC=97=85=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EC=88=98=EC=A0=95=20DTO=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/businesshours/dto/BusinessHoursReqDto.java | 8 ++++++++ .../domain/businesshours/dto/BusinessHoursResDto.java | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java index be14695..8090c03 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java @@ -1,11 +1,13 @@ package com.eatsfine.eatsfine.domain.businesshours.dto; import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.Builder; import java.time.DayOfWeek; import java.time.LocalTime; +import java.util.List; public class BusinessHoursReqDto { @@ -23,4 +25,10 @@ public record Summary( boolean isClosed ){} + + @Builder + public record UpdateBusinessHoursDto( + @Valid + List businessHours + ){} } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java index bae2100..4521ecf 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java @@ -5,6 +5,7 @@ import java.time.DayOfWeek; import java.time.LocalTime; +import java.util.List; public class BusinessHoursResDto { @@ -20,4 +21,10 @@ public record Summary( boolean isClosed // true = 휴무, false = 영업 ){} + + @Builder + public record UpdateBusinessHoursDto( + Long storeId, + List updatedDays + ){} } From 1e499880e55fcda4dcd291b4fe4f624e8a0233e0 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Fri, 16 Jan 2026 01:07:15 +0900 Subject: [PATCH 08/14] =?UTF-8?q?[FEAT]:=20=EC=9D=91=EB=8B=B5=20=EC=BB=A8?= =?UTF-8?q?=EB=B2=84=ED=84=B0=20=EB=B0=8F=20=EC=83=81=ED=83=9C=EC=BD=94?= =?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 --- .../converter/BusinessHoursConverter.java | 9 +++++ .../status/BusinessHoursErrorStatus.java | 11 +++--- .../status/BusinessHoursSuccessStatus.java | 39 +++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java index ff7d01b..58430dc 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java @@ -4,6 +4,8 @@ import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursResDto; import com.eatsfine.eatsfine.domain.businesshours.entity.BusinessHours; +import java.util.List; + public class BusinessHoursConverter { public static BusinessHours toEntity(BusinessHoursReqDto.Summary dto) { @@ -33,4 +35,11 @@ public static BusinessHoursResDto.Summary toSummary(BusinessHours bh) { .isClosed(false) .build(); } + + public static BusinessHoursResDto.UpdateBusinessHoursDto toUpdateBusinessHoursDto(Long storeId, List updatedDays) { + return BusinessHoursResDto.UpdateBusinessHoursDto.builder() + .storeId(storeId) + .updatedDays(updatedDays) + .build(); + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java index e9a9310..b9910bf 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java @@ -10,11 +10,12 @@ @RequiredArgsConstructor public enum BusinessHoursErrorStatus implements BaseErrorCode { - _DUPLICATE_DAY_OF_WEEK(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_400_1", "요일이 중복되었습니다."), - _BUSINESS_HOURS_NOT_COMPLETE(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_400_2", "영업일은 7일 모두 입력되어야 합니다."), - _INVALID_BUSINESS_TIME(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_400_3", "영업 시작 시간은 마감 시간보다 빨라야 합니다."), - _INVALID_OPEN_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_400_4", "영업일에는 영업시간 및 마감 시간이 존재해야 합니다."), - _INVALID_CLOSED_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_400_5", "휴무일에는 영업시간이 존재할 수 없습니다."), + _DUPLICATE_DAY_OF_WEEK(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4001", "요일이 중복되었습니다."), + _BUSINESS_HOURS_NOT_COMPLETE(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4002", "영업일은 7일 모두 입력되어야 합니다."), + _INVALID_BUSINESS_TIME(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4003", "영업 시작 시간은 마감 시간보다 빨라야 합니다."), + _INVALID_OPEN_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_4004", "영업일에는 영업시간 및 마감 시간이 존재해야 합니다."), + _INVALID_CLOSED_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_4005", "휴무일에는 영업시간이 존재할 수 없습니다."), + _BUSINESS_HOURS_DAY_NOT_FOUND(HttpStatus.NOT_FOUND, "BUSINESS_HOURS_404", "해당 요일이 존재하지 않습니다.") ; diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java new file mode 100644 index 0000000..dd665b9 --- /dev/null +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java @@ -0,0 +1,39 @@ +package com.eatsfine.eatsfine.domain.businesshours.status; + +import com.eatsfine.eatsfine.global.apiPayload.code.BaseCode; +import com.eatsfine.eatsfine.global.apiPayload.code.ReasonDto; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum BusinessHoursSuccessStatus implements BaseCode { + + _UPDATE_BUSINESS_HOURS_SUCCESS(HttpStatus.OK, "BUSINESS_HOURS200", "영업시간이 성공적으로 수정되었습니다."), + ; + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + + @Override + public ReasonDto getReason() { + return ReasonDto.builder() + .isSuccess(false) + .code(code) + .message(message) + .build(); + } + + @Override + public ReasonDto getReasonHttpStatus() { + return ReasonDto.builder() + .httpStatus(httpStatus) + .isSuccess(false) + .code(code) + .message(message) + .build(); + } +} From 0d929f61a8d6b0631630062d43529d35fe00ddb4 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Fri, 16 Jan 2026 01:08:47 +0900 Subject: [PATCH 09/14] =?UTF-8?q?[FEAT]:=20=EC=98=81=EC=97=85=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BusinessHoursController.java | 36 +++++++++++++ .../businesshours/entity/BusinessHours.java | 6 +++ .../service/BusinessHoursCommandService.java | 11 ++++ .../BusinessHoursCommandServiceImpl.java | 52 +++++++++++++++++++ .../eatsfine/domain/store/entity/Store.java | 12 +++++ 5 files changed, 117 insertions(+) create mode 100644 src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java create mode 100644 src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java create mode 100644 src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java new file mode 100644 index 0000000..6ac0262 --- /dev/null +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java @@ -0,0 +1,36 @@ +package com.eatsfine.eatsfine.domain.businesshours.controller; + +import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursReqDto; +import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursResDto; +import com.eatsfine.eatsfine.domain.businesshours.service.BusinessHoursCommandService; +import com.eatsfine.eatsfine.domain.businesshours.status.BusinessHoursSuccessStatus; +import com.eatsfine.eatsfine.global.apiPayload.ApiResponse; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class BusinessHoursController { + + private final BusinessHoursCommandService businessHoursCommandService; + + @Operation( + summary = "가게 영업시간 수정", + description = "가게의 영업시간을 수정합니다." + ) + @PatchMapping("/stores/{storeId}/business-hours") + public ApiResponse updateBusinessHours( + @PathVariable Long storeId, + @RequestBody BusinessHoursReqDto.UpdateBusinessHoursDto dto + ){ + return ApiResponse.of( + BusinessHoursSuccessStatus._UPDATE_BUSINESS_HOURS_SUCCESS, + businessHoursCommandService.updateBusinessHours(storeId, dto) + ); + } + +} diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java index 61883ae..d1ee0c8 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java @@ -47,4 +47,10 @@ public class BusinessHours extends BaseEntity { public void assignStore(Store store){ this.store = store; } + + public void update(LocalTime open, LocalTime close, boolean isClosed){ + this.openTime = open; + this.closeTime = close; + this.isHoliday = isClosed; + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java new file mode 100644 index 0000000..a6dce41 --- /dev/null +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java @@ -0,0 +1,11 @@ +package com.eatsfine.eatsfine.domain.businesshours.service; + +import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursReqDto; +import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursResDto; + +public interface BusinessHoursCommandService { + BusinessHoursResDto.UpdateBusinessHoursDto updateBusinessHours( + Long storeId, + BusinessHoursReqDto.UpdateBusinessHoursDto updateBusinessHoursDto + ); +} diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java new file mode 100644 index 0000000..8552a89 --- /dev/null +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java @@ -0,0 +1,52 @@ +package com.eatsfine.eatsfine.domain.businesshours.service; + +import com.eatsfine.eatsfine.domain.businesshours.converter.BusinessHoursConverter; +import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursReqDto; +import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursResDto; +import com.eatsfine.eatsfine.domain.businesshours.entity.BusinessHours; +import com.eatsfine.eatsfine.domain.businesshours.validator.BusinessHoursValidator; +import com.eatsfine.eatsfine.domain.store.entity.Store; +import com.eatsfine.eatsfine.domain.store.exception.StoreException; +import com.eatsfine.eatsfine.domain.store.repository.StoreRepository; +import com.eatsfine.eatsfine.domain.store.status.StoreErrorStatus; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.DayOfWeek; +import java.util.ArrayList; +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class BusinessHoursCommandServiceImpl implements BusinessHoursCommandService { + + StoreRepository storeRepository; + + @Override + public BusinessHoursResDto.UpdateBusinessHoursDto updateBusinessHours( + Long storeId, + BusinessHoursReqDto.UpdateBusinessHoursDto dto + ) { + // 영업시간 검증 + BusinessHoursValidator.validateForUpdate(dto.businessHours()); + + Store store = storeRepository.findById(storeId) + .orElseThrow(() -> new StoreException(StoreErrorStatus._STORE_NOT_FOUND)); + + List updatedDays = new ArrayList<>(); + + dto.businessHours().forEach(s -> { + store.updateBusinessHours( + s.dayOfWeek(), + s.openTime(), + s.closeTime(), + s.isClosed() + ); + updatedDays.add(s.dayOfWeek().toString()); + }); + + return BusinessHoursConverter.toUpdateBusinessHoursDto(storeId, updatedDays); + } +} diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java b/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java index e555565..9f8dc34 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/entity/Store.java @@ -1,6 +1,8 @@ package com.eatsfine.eatsfine.domain.store.entity; import com.eatsfine.eatsfine.domain.businesshours.entity.BusinessHours; +import com.eatsfine.eatsfine.domain.businesshours.exception.BusinessHoursException; +import com.eatsfine.eatsfine.domain.businesshours.status.BusinessHoursErrorStatus; import com.eatsfine.eatsfine.domain.region.entity.Region; import com.eatsfine.eatsfine.domain.store.dto.StoreReqDto; import com.eatsfine.eatsfine.domain.store.enums.Category; @@ -17,6 +19,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.DayOfWeek; +import java.time.LocalTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -108,6 +111,15 @@ public void removeBusinessHours(BusinessHours businessHours) { businessHours.assignStore(null); } + // 영업시간 변경 + public void updateBusinessHours(DayOfWeek dayOfWeek, LocalTime open, LocalTime close, boolean isClosed) { + BusinessHours businessHours = this.businessHours.stream() + .filter(bh -> bh.getDayOfWeek() == dayOfWeek) + .findFirst() + .orElseThrow(() -> new BusinessHoursException(BusinessHoursErrorStatus._BUSINESS_HOURS_DAY_NOT_FOUND)); + + businessHours.update(open, close, isClosed); + } public void addTableImage(TableImage tableImage) { this.tableImages.add(tableImage); tableImage.assignStore(this); From 75a1a38775aa7cec8d732e99f34925699fa88494 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Sat, 17 Jan 2026 16:15:43 +0900 Subject: [PATCH 10/14] =?UTF-8?q?[REFACTOR]:=20=EC=98=81=EC=97=85=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EB=B3=80=EA=B2=BD=20=EC=9D=91=EB=8B=B5=207?= =?UTF-8?q?=EC=9D=BC=20=EB=AA=A8=EB=91=90=20=EB=82=B4=EB=A0=A4=EC=A3=BC?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BusinessHoursController.java | 8 ++++---- .../converter/BusinessHoursConverter.java | 16 +++++++++++----- .../businesshours/dto/BusinessHoursReqDto.java | 2 +- .../businesshours/dto/BusinessHoursResDto.java | 2 +- .../businesshours/entity/BusinessHours.java | 6 +++--- .../service/BusinessHoursCommandServiceImpl.java | 12 ++---------- .../validator/BusinessHoursValidator.java | 2 +- .../domain/store/controller/StoreController.java | 2 +- .../store/service/StoreQueryServiceImpl.java | 2 +- 9 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java index 6ac0262..7e439a5 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java @@ -6,12 +6,12 @@ import com.eatsfine.eatsfine.domain.businesshours.status.BusinessHoursSuccessStatus; import com.eatsfine.eatsfine.global.apiPayload.ApiResponse; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +@Tag(name = "BusinessHours", description = "영업시간 관련 API") +@RequestMapping("/api/v1") @RestController @RequiredArgsConstructor public class BusinessHoursController { diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java index 58430dc..a143bb2 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java @@ -10,10 +10,10 @@ public class BusinessHoursConverter { public static BusinessHours toEntity(BusinessHoursReqDto.Summary dto) { return BusinessHours.builder() - .dayOfWeek(dto.dayOfWeek()) + .dayOfWeek(dto.day()) .openTime(dto.openTime()) .closeTime(dto.closeTime()) - .isHoliday(dto.isClosed()) // 특정 요일 고정 휴무 + .isClosed(dto.isClosed()) // 특정 요일 고정 휴무 .build(); } @@ -21,9 +21,11 @@ public static BusinessHours toEntity(BusinessHoursReqDto.Summary dto) { public static BusinessHoursResDto.Summary toSummary(BusinessHours bh) { // 휴무일 때 - if(bh.isHoliday()) { + if(bh.isClosed()) { return BusinessHoursResDto.Summary.builder() .day(bh.getDayOfWeek()) + .openTime(null) + .closeTime(null) .isClosed(true) .build(); } @@ -36,10 +38,14 @@ public static BusinessHoursResDto.Summary toSummary(BusinessHours bh) { .build(); } - public static BusinessHoursResDto.UpdateBusinessHoursDto toUpdateBusinessHoursDto(Long storeId, List updatedDays) { + public static BusinessHoursResDto.UpdateBusinessHoursDto toUpdateBusinessHoursDto(Long storeId, List updatedBusinessHours) { return BusinessHoursResDto.UpdateBusinessHoursDto.builder() .storeId(storeId) - .updatedDays(updatedDays) + .updatedBusinessHours( + updatedBusinessHours.stream().map( + BusinessHoursConverter::toSummary + ).toList() + ) .build(); } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java index 8090c03..310c9cb 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java @@ -15,7 +15,7 @@ public class BusinessHoursReqDto { public record Summary( @NotNull(message = "요일은 필수입니다.") - DayOfWeek dayOfWeek, + DayOfWeek day, @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") LocalTime openTime, diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java index 4521ecf..db9a571 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java @@ -25,6 +25,6 @@ public record Summary( @Builder public record UpdateBusinessHoursDto( Long storeId, - List updatedDays + List updatedBusinessHours ){} } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java index d1ee0c8..4377599 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java @@ -41,8 +41,8 @@ public class BusinessHours extends BaseEntity { // 휴일 여부 (특정 요일 고정 휴무) @Builder.Default - @Column(name = "is_holiday", nullable = false) - private boolean isHoliday = false; + @Column(name = "is_closed", nullable = false) + private boolean isClosed = false; public void assignStore(Store store){ this.store = store; @@ -51,6 +51,6 @@ public void assignStore(Store store){ public void update(LocalTime open, LocalTime close, boolean isClosed){ this.openTime = open; this.closeTime = close; - this.isHoliday = isClosed; + this.isClosed = isClosed; } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java index 8552a89..b489f2b 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java @@ -3,7 +3,6 @@ import com.eatsfine.eatsfine.domain.businesshours.converter.BusinessHoursConverter; import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursReqDto; import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursResDto; -import com.eatsfine.eatsfine.domain.businesshours.entity.BusinessHours; import com.eatsfine.eatsfine.domain.businesshours.validator.BusinessHoursValidator; import com.eatsfine.eatsfine.domain.store.entity.Store; import com.eatsfine.eatsfine.domain.store.exception.StoreException; @@ -13,10 +12,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.DayOfWeek; -import java.util.ArrayList; -import java.util.List; - @Service @Transactional @RequiredArgsConstructor @@ -35,18 +30,15 @@ public BusinessHoursResDto.UpdateBusinessHoursDto updateBusinessHours( Store store = storeRepository.findById(storeId) .orElseThrow(() -> new StoreException(StoreErrorStatus._STORE_NOT_FOUND)); - List updatedDays = new ArrayList<>(); - dto.businessHours().forEach(s -> { store.updateBusinessHours( - s.dayOfWeek(), + s.day(), s.openTime(), s.closeTime(), s.isClosed() ); - updatedDays.add(s.dayOfWeek().toString()); }); - return BusinessHoursConverter.toUpdateBusinessHoursDto(storeId, updatedDays); + return BusinessHoursConverter.toUpdateBusinessHoursDto(storeId, store.getBusinessHours()); } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java index b9bc7dc..6313b7e 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BusinessHoursValidator.java @@ -48,7 +48,7 @@ private static void validateOpenCloseTime(List dto) private static void validateDuplicateDayOfWeek(List dto) { Set set = new HashSet<>(); for(BusinessHoursReqDto.Summary s: dto) { - if(!set.add(s.dayOfWeek())) { + if(!set.add(s.day())) { throw new BusinessHoursException(BusinessHoursErrorStatus._DUPLICATE_DAY_OF_WEEK); } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java b/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java index 209cbdf..6527f47 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/controller/StoreController.java @@ -59,7 +59,7 @@ public ApiResponse getStoreDetail(@PathVariable Long @Operation( summary = "가게 기본 정보 수정", - description = "가게 기본 정보(단일 필드)를 수정합니다. " + + description = "가게 기본 정보(영업시간, 브레이크타임 제외)를 수정합니다. " + "영업시간, 브레이크타임, 이미지는 별도 엔티티/컬렉션이므로 개별 API로 분리" ) @PatchMapping("/stores/{storeId}") diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreQueryServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreQueryServiceImpl.java index 7db9255..2c93816 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreQueryServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/service/StoreQueryServiceImpl.java @@ -81,7 +81,7 @@ public boolean isOpenNow(Store store, LocalDateTime now) { return store.findBusinessHoursByDay(dayOfWeek) .map(bh -> { - if (bh.isHoliday()) return false; + if (bh.isClosed()) return false; if ((bh.getBreakStartTime() != null && bh.getBreakEndTime() != null)) { if (!time.isBefore(bh.getBreakStartTime()) && (time.isBefore(bh.getBreakEndTime()))) { From 7b422b1061d8f3043514b79908e9b18e7273fa0c Mon Sep 17 00:00:00 2001 From: twodo0 Date: Sat, 17 Jan 2026 18:24:31 +0900 Subject: [PATCH 11/14] =?UTF-8?q?[FEAT]:=20=EB=B8=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=ED=81=AC=ED=83=80=EC=9E=84=20=EC=84=A4=EC=A0=95=20DTO=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9D=91=EB=8B=B5=EC=BD=94=EB=93=9C=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 --- .../businesshours/dto/BusinessHoursReqDto.java | 12 ++++++++++++ .../businesshours/dto/BusinessHoursResDto.java | 13 +++++++++++++ .../status/BusinessHoursErrorStatus.java | 9 ++++++--- .../status/BusinessHoursSuccessStatus.java | 1 + 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java index 310c9cb..10db26c 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursReqDto.java @@ -31,4 +31,16 @@ public record UpdateBusinessHoursDto( @Valid List businessHours ){} + + @Builder + public record UpdateBreakTimeDto( + + @NotNull(message = "브레이크타임 시작 시간은 필수입니다.") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + LocalTime breakStartTime, + + @NotNull(message = "브레이크타임 종료 시간은 필수입니다.") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + LocalTime breakEndTime + ){} } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java index db9a571..d767486 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/dto/BusinessHoursResDto.java @@ -22,9 +22,22 @@ public record Summary( boolean isClosed // true = 휴무, false = 영업 ){} + // 영업시간 수정 응답 @Builder public record UpdateBusinessHoursDto( Long storeId, List updatedBusinessHours ){} + + // 브레이크타임 설정 응답 + @Builder + public record UpdateBreakTimeDto( + Long storeId, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + LocalTime breakStartTime, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + LocalTime breakEndTime + ){} } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java index b9910bf..59e1331 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursErrorStatus.java @@ -13,12 +13,15 @@ public enum BusinessHoursErrorStatus implements BaseErrorCode { _DUPLICATE_DAY_OF_WEEK(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4001", "요일이 중복되었습니다."), _BUSINESS_HOURS_NOT_COMPLETE(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4002", "영업일은 7일 모두 입력되어야 합니다."), _INVALID_BUSINESS_TIME(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4003", "영업 시작 시간은 마감 시간보다 빨라야 합니다."), - _INVALID_OPEN_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_4004", "영업일에는 영업시간 및 마감 시간이 존재해야 합니다."), - _INVALID_CLOSED_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS_4005", "휴무일에는 영업시간이 존재할 수 없습니다."), - _BUSINESS_HOURS_DAY_NOT_FOUND(HttpStatus.NOT_FOUND, "BUSINESS_HOURS_404", "해당 요일이 존재하지 않습니다.") + _INVALID_OPEN_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4004", "영업일에는 영업시간 및 마감 시간이 존재해야 합니다."), + _INVALID_CLOSED_DAY(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4005", "휴무일에는 영업시간이 존재할 수 없습니다."), + _BUSINESS_HOURS_DAY_NOT_FOUND(HttpStatus.NOT_FOUND, "BUSINESS_HOURS404", "해당 요일이 존재하지 않습니다."), + _INVALID_BREAK_TIME(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4006", "브레이크타임 시작 시간은 종료 시간보다 빨라야 합니다."), + _BREAK_TIME_OUT_OF_BUSINESS_HOURS(HttpStatus.BAD_REQUEST, "BUSINESS_HOURS4007", "브레이크타임은 영업시간 내에만 설정할 수 있습니다."), ; + private final HttpStatus httpStatus; private final String code; private final String message; diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java index dd665b9..b0a12e4 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/status/BusinessHoursSuccessStatus.java @@ -11,6 +11,7 @@ public enum BusinessHoursSuccessStatus implements BaseCode { _UPDATE_BUSINESS_HOURS_SUCCESS(HttpStatus.OK, "BUSINESS_HOURS200", "영업시간이 성공적으로 수정되었습니다."), + _UPDATE_BREAKTIME_SUCCESS(HttpStatus.OK, "BUSINESS_HOURS2001", "브레이크타임이 성공적으로 설정되었습니다.") ; private final HttpStatus httpStatus; From 13fd6524b39b520a43221e8b78a8896364104ff4 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Sat, 17 Jan 2026 18:25:46 +0900 Subject: [PATCH 12/14] =?UTF-8?q?[FEAT]:=20=EC=9A=94=EC=B2=AD=EB=90=9C=20?= =?UTF-8?q?=EB=B8=8C=EB=A0=88=EC=9D=B4=ED=81=AC=ED=83=80=EC=9E=84=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../validator/BreakTimeValidator.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BreakTimeValidator.java diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BreakTimeValidator.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BreakTimeValidator.java new file mode 100644 index 0000000..a8766dd --- /dev/null +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/validator/BreakTimeValidator.java @@ -0,0 +1,29 @@ +package com.eatsfine.eatsfine.domain.businesshours.validator; + +import com.eatsfine.eatsfine.domain.businesshours.exception.BusinessHoursException; +import com.eatsfine.eatsfine.domain.businesshours.status.BusinessHoursErrorStatus; + +import java.time.LocalTime; + +public class BreakTimeValidator { + + public static void validateBreakTime(LocalTime openTime, LocalTime closeTime, LocalTime breakStartTime, LocalTime breakEndTime) { + + // 휴무일은 검증 대상이 아님 + if(openTime == null || closeTime == null) { + return; + } + + // start < end + if(!breakEndTime.isAfter(breakStartTime)) { + throw new BusinessHoursException(BusinessHoursErrorStatus._INVALID_BREAK_TIME); + } + + // 브레이크타임이 영업시간 내에 존재 + if(breakStartTime.isBefore(openTime) || breakEndTime.isAfter(closeTime)) { + throw new BusinessHoursException(BusinessHoursErrorStatus._BREAK_TIME_OUT_OF_BUSINESS_HOURS); + } + + + } +} From 7d8aa7a20c64b9b9777128fb27f54ecc2add3a6f Mon Sep 17 00:00:00 2001 From: twodo0 Date: Sat, 17 Jan 2026 18:26:42 +0900 Subject: [PATCH 13/14] =?UTF-8?q?[FEAT]:=20=EB=B8=8C=EB=A0=88=EC=9D=B4?= =?UTF-8?q?=ED=81=AC=ED=83=80=EC=9E=84=20=EC=84=A4=EC=A0=95=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/BusinessHoursController.java | 15 +++++++++++ .../converter/BusinessHoursConverter.java | 8 ++++++ .../businesshours/entity/BusinessHours.java | 7 +++++ .../service/BusinessHoursCommandService.java | 6 +++++ .../BusinessHoursCommandServiceImpl.java | 26 ++++++++++++++++++- 5 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java index 7e439a5..3c0aa8f 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/controller/BusinessHoursController.java @@ -33,4 +33,19 @@ public ApiResponse updateBusinessHou ); } + @Operation( + summary = "브레이크타임 설정", + description = "가게의 브레이크타임을 설정합니다." + ) + @PatchMapping("/stores/{storeId}/break-time") + public ApiResponse updateBreakTime( + @PathVariable Long storeId, + @RequestBody BusinessHoursReqDto.UpdateBreakTimeDto dto + ){ + return ApiResponse.of( + BusinessHoursSuccessStatus._UPDATE_BREAKTIME_SUCCESS, + businessHoursCommandService.updateBreakTime(storeId, dto) + ); + } + } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java index a143bb2..e74b337 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/converter/BusinessHoursConverter.java @@ -48,4 +48,12 @@ public static BusinessHoursResDto.UpdateBusinessHoursDto toUpdateBusinessHoursDt ) .build(); } + + public static BusinessHoursResDto.UpdateBreakTimeDto toUpdateBreakTimeDto(Long storeId, BusinessHoursReqDto.UpdateBreakTimeDto dto) { + return BusinessHoursResDto.UpdateBreakTimeDto.builder() + .storeId(storeId) + .breakStartTime(dto.breakStartTime()) + .breakEndTime(dto.breakEndTime()) + .build(); + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java index 4377599..b9a332f 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/entity/BusinessHours.java @@ -48,9 +48,16 @@ public void assignStore(Store store){ this.store = store; } + // 영업시간 변경 public void update(LocalTime open, LocalTime close, boolean isClosed){ this.openTime = open; this.closeTime = close; this.isClosed = isClosed; } + + // 브레이크타임 변경 + public void updateBreakTime(LocalTime breakStart, LocalTime breakEnd){ + this.breakStartTime = breakStart; + this.breakEndTime = breakEnd; + } } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java index a6dce41..e752624 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandService.java @@ -8,4 +8,10 @@ BusinessHoursResDto.UpdateBusinessHoursDto updateBusinessHours( Long storeId, BusinessHoursReqDto.UpdateBusinessHoursDto updateBusinessHoursDto ); + + BusinessHoursResDto.UpdateBreakTimeDto updateBreakTime( + Long storeId, + BusinessHoursReqDto.UpdateBreakTimeDto dto + ); + } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java index b489f2b..d5416dd 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/businesshours/service/BusinessHoursCommandServiceImpl.java @@ -3,6 +3,8 @@ import com.eatsfine.eatsfine.domain.businesshours.converter.BusinessHoursConverter; import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursReqDto; import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursResDto; +import com.eatsfine.eatsfine.domain.businesshours.entity.BusinessHours; +import com.eatsfine.eatsfine.domain.businesshours.validator.BreakTimeValidator; import com.eatsfine.eatsfine.domain.businesshours.validator.BusinessHoursValidator; import com.eatsfine.eatsfine.domain.store.entity.Store; import com.eatsfine.eatsfine.domain.store.exception.StoreException; @@ -17,7 +19,7 @@ @RequiredArgsConstructor public class BusinessHoursCommandServiceImpl implements BusinessHoursCommandService { - StoreRepository storeRepository; + private final StoreRepository storeRepository; @Override public BusinessHoursResDto.UpdateBusinessHoursDto updateBusinessHours( @@ -41,4 +43,26 @@ public BusinessHoursResDto.UpdateBusinessHoursDto updateBusinessHours( return BusinessHoursConverter.toUpdateBusinessHoursDto(storeId, store.getBusinessHours()); } + + @Override + public BusinessHoursResDto.UpdateBreakTimeDto updateBreakTime( + Long storeId, + BusinessHoursReqDto.UpdateBreakTimeDto dto + ) { + Store store = storeRepository.findById(storeId) + .orElseThrow(() -> new StoreException(StoreErrorStatus._STORE_NOT_FOUND)); + + for(BusinessHours bh : store.getBusinessHours()) { + if(bh.isClosed()) continue; + BreakTimeValidator.validateBreakTime(bh.getOpenTime(), bh.getCloseTime(), dto.breakStartTime(), dto.breakEndTime()); + } + + store.getBusinessHours().forEach(s -> { + if(!s.isClosed()) { + s.updateBreakTime(dto.breakStartTime(), dto.breakEndTime()); + } + }); + + return BusinessHoursConverter.toUpdateBreakTimeDto(storeId, dto); + } } From 562915ef0b746f331eaf505920f8cf3bbdd47654 Mon Sep 17 00:00:00 2001 From: twodo0 Date: Sat, 17 Jan 2026 23:19:17 +0900 Subject: [PATCH 14/14] =?UTF-8?q?[FEAT]:=20=EC=83=81=EC=84=B8=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=9D=91=EB=8B=B5=EC=97=90=20=EB=B8=8C=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=ED=81=AC=ED=83=80=EC=9E=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eatsfine/domain/store/converter/StoreConverter.java | 8 ++++++++ .../eatsfine/eatsfine/domain/store/dto/StoreResDto.java | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java b/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java index 85fd44e..11f7ac4 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/converter/StoreConverter.java @@ -1,6 +1,7 @@ package com.eatsfine.eatsfine.domain.store.converter; import com.eatsfine.eatsfine.domain.businesshours.converter.BusinessHoursConverter; +import com.eatsfine.eatsfine.domain.businesshours.entity.BusinessHours; import com.eatsfine.eatsfine.domain.store.dto.StoreResDto; import com.eatsfine.eatsfine.domain.store.entity.Store; @@ -31,6 +32,11 @@ public static StoreResDto.StoreSearchDto toSearchDto(Store store, Double distanc } public static StoreResDto.StoreDetailDto toDetailDto(Store store, boolean isOpenNow) { + BusinessHours anyOpenDay = store.getBusinessHours().stream() + .filter(bh -> !bh.isClosed()) + .findFirst() + .orElse(null); + return StoreResDto.StoreDetailDto.builder() .storeId(store.getId()) .storeName(store.getStoreName()) @@ -47,6 +53,8 @@ public static StoreResDto.StoreDetailDto toDetailDto(Store store, boolean isOpen store.getBusinessHours().stream() .map(BusinessHoursConverter::toSummary) .toList()) + .breakStartTime(anyOpenDay != null ? anyOpenDay.getBreakStartTime() : null) + .breakEndTime(anyOpenDay != null ? anyOpenDay.getBreakEndTime() : null) .isOpenNow(isOpenNow) // 추후 영업 여부 판단 로직 구현 예정 .build(); } diff --git a/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java b/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java index ca3fcee..a674eaa 100644 --- a/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java +++ b/src/main/java/com/eatsfine/eatsfine/domain/store/dto/StoreResDto.java @@ -2,9 +2,11 @@ import com.eatsfine.eatsfine.domain.businesshours.dto.BusinessHoursResDto; import com.eatsfine.eatsfine.domain.store.enums.Category; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; import java.math.BigDecimal; +import java.time.LocalTime; import java.util.List; public class StoreResDto { @@ -56,6 +58,13 @@ public record StoreDetailDto( String mainImageUrl, List tableImageUrls, List businessHours, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + LocalTime breakStartTime, + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm") + LocalTime breakEndTime, + boolean isOpenNow ){}