diff --git a/oneco/src/main/java/com/oneco/backend/mission/application/port/in/ApproveMissionUseCase.java b/oneco/src/main/java/com/oneco/backend/mission/application/port/in/ApproveMissionUseCase.java index c22fc84..8d6dd3b 100644 --- a/oneco/src/main/java/com/oneco/backend/mission/application/port/in/ApproveMissionUseCase.java +++ b/oneco/src/main/java/com/oneco/backend/mission/application/port/in/ApproveMissionUseCase.java @@ -5,5 +5,6 @@ public interface ApproveMissionUseCase { + // 미션 수신자는 미션 승인 또는 거절을 결정한다. MissionResult decide(ApproveMissionCommand command); } diff --git a/oneco/src/main/java/com/oneco/backend/mission/application/service/CreateMissionService.java b/oneco/src/main/java/com/oneco/backend/mission/application/service/CreateMissionService.java index 8d1b7d6..94f8e47 100644 --- a/oneco/src/main/java/com/oneco/backend/mission/application/service/CreateMissionService.java +++ b/oneco/src/main/java/com/oneco/backend/mission/application/service/CreateMissionService.java @@ -69,7 +69,7 @@ public MissionResult request(CreateMissionCommand command) { Reward reward = Reward.of(title, command.message()); // Mission 생성시 필요한 값: FamilyRelationId, CategoryId, Period, Reward(nullable) - Mission mission = Mission.create(requesterId, recipientId, relationId, categoryId, period, reward); + Mission mission = Mission.of(requesterId, recipientId, relationId, categoryId, period, reward); // 3. 저장 missionPort.save(mission); diff --git a/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionApprovalService.java b/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionApprovalService.java index a0618d9..87aa66d 100644 --- a/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionApprovalService.java +++ b/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionApprovalService.java @@ -1,5 +1,7 @@ package com.oneco.backend.mission.application.service; +import java.time.LocalDate; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,9 +33,20 @@ public MissionResult decide(ApproveMissionCommand command) { MemberId recipientId = MemberId.of(command.recipientId()); validateRecipient(mission, recipientId); validateStatus(mission); + validateNotExpired(mission); if (command.accepted()) { + // 미션 승인 상태일 경우 mission.acceptApproval(); + + // 미션 시작일이 오늘(요청 수락일)과 같거나 이전이라면 즉시 미션 진행 상태로 변경 + LocalDate startDate = mission.getPeriod().getStartDate(); + LocalDate today = LocalDate.now(); + + if (startDate.isBefore(today) || startDate.isEqual(today)) { + mission.markInProgress(); // 미션을 즉시 진행 상태로 변경 + } + } else { mission.rejectApproval(); } @@ -44,7 +57,8 @@ public MissionResult decide(ApproveMissionCommand command) { private void validateRecipient(Mission mission, MemberId recipientId) { if (!mission.getRecipientId().equals(recipientId)) { - throw BaseException.from(MissionErrorCode.MISSION_APPROVAL_FORBIDDEN); + throw BaseException.from(MissionErrorCode.MISSION_APPROVAL_FORBIDDEN, + "미션 수신자가 아닌 사용자는 승인/거절할 수 없습니다."); } } @@ -54,4 +68,12 @@ private void validateStatus(Mission mission) { "승인/거절은 APPROVAL_REQUEST 상태에서만 가능합니다."); } } + + private void validateNotExpired(Mission mission) { + LocalDate today = LocalDate.now(); + if (today.isAfter(mission.getPeriod().getEndDate())) { + throw BaseException.from(MissionErrorCode.LATE_MISSION_APPROVAL, + "미션 종료일이 지난 후에는 승인할 수 없습니다."); + } + } } diff --git a/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionBatchService.java b/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionBatchService.java index e7b2624..792b826 100644 --- a/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionBatchService.java +++ b/oneco/src/main/java/com/oneco/backend/mission/application/service/MissionBatchService.java @@ -80,7 +80,7 @@ public void startScheduledMissions() { long successCount = 0; // 성공 처리 건수 long errorCount = 0; // 실패 처리 중 오류 발생 건수 - // 1. 오늘이 시작일인 미션들을 조회한다. + // 1. 오늘이 시작일이면서 미션 상태가 APPROVAL_ACCEPTED인 미션들을 조회한다. List missionsToStart = missionPort.findAllMissionsStartingToday(today); // ============================= diff --git a/oneco/src/main/java/com/oneco/backend/mission/domain/exception/MissionErrorCode.java b/oneco/src/main/java/com/oneco/backend/mission/domain/exception/MissionErrorCode.java index c2e5838..b4a3530 100644 --- a/oneco/src/main/java/com/oneco/backend/mission/domain/exception/MissionErrorCode.java +++ b/oneco/src/main/java/com/oneco/backend/mission/domain/exception/MissionErrorCode.java @@ -120,6 +120,11 @@ public enum MissionErrorCode implements ErrorCode { HttpStatus.BAD_REQUEST, "미션 ID가 유효하지 않습니다.", "MISSION_ERROR_400_INVALID_MISSION_ID" + ), + LATE_MISSION_APPROVAL( + HttpStatus.BAD_REQUEST, + "미션 종료일이 지난 후에는 승인할 수 없습니다.", + "MISSION_ERROR_400_LATE_MISSION_APPROVAL" ); private final HttpStatus httpStatus; diff --git a/oneco/src/main/java/com/oneco/backend/mission/domain/mission/Mission.java b/oneco/src/main/java/com/oneco/backend/mission/domain/mission/Mission.java index 3a4b43c..11ba99b 100644 --- a/oneco/src/main/java/com/oneco/backend/mission/domain/mission/Mission.java +++ b/oneco/src/main/java/com/oneco/backend/mission/domain/mission/Mission.java @@ -106,7 +106,7 @@ private Mission( } // 미션 생성 메서드 - public static Mission create( + public static Mission of( MemberId requesterId, MemberId recipientId, FamilyRelationId familyRelationId, diff --git a/oneco/src/main/java/com/oneco/backend/mission/presentation/MissionController.java b/oneco/src/main/java/com/oneco/backend/mission/presentation/MissionController.java index df77f71..8ee06d0 100644 --- a/oneco/src/main/java/com/oneco/backend/mission/presentation/MissionController.java +++ b/oneco/src/main/java/com/oneco/backend/mission/presentation/MissionController.java @@ -75,8 +75,10 @@ public ResponseEntity> createMission( description = """ - 미션 승인 또는 거절 요청을 처리한다. - 미션 수신자는 미션을 승인하거나 거절할 수 있다. - - 승인 시 미션 상태는 '진행중'으로 변경된다. + - 승인 시 미션 상태는 '승인 수락'으로 변경된다. - 거절 시 미션 상태는 '거절됨'으로 변경된다. + - 미션 승인 시점이 미션 시작일이과 같을 경우 미션 상태는 즉시 '진행중'으로 변경된다. + - 미션 승인 시점이 미션 시작일보다 이후 일 경우 미션 상태는 즉시 '진행중'으로 변경된다. """ ) @ApiResponses({