diff --git a/src/main/java/com/run_us/server/domains/crew/controller/CrewController.java b/src/main/java/com/run_us/server/domains/crew/controller/CrewController.java index abbb2067..6dfd7be6 100644 --- a/src/main/java/com/run_us/server/domains/crew/controller/CrewController.java +++ b/src/main/java/com/run_us/server/domains/crew/controller/CrewController.java @@ -1,11 +1,10 @@ package com.run_us.server.domains.crew.controller; -import com.run_us.server.domains.crew.controller.model.request.CreateJoinRequest; -import com.run_us.server.domains.crew.controller.model.request.ReviewJoinRequest; +import com.run_us.server.domains.crew.controller.model.request.*; import com.run_us.server.domains.crew.controller.model.response.*; import com.run_us.server.domains.crew.domain.enums.CrewJoinRequestStatus; +import com.run_us.server.domains.crew.service.usecase.CommandCrewUseCase; import com.run_us.server.domains.crew.service.usecase.CrewJoinUseCase; -import com.run_us.server.domains.crew.controller.model.request.CreateCrewRequest; import com.run_us.server.domains.crew.controller.model.response.CreateCrewResponse; import com.run_us.server.domains.crew.service.usecase.CreateCrewUseCase; import com.run_us.server.domains.crew.service.usecase.CrewMemberUseCase; @@ -30,19 +29,51 @@ public class CrewController { private final CrewJoinUseCase crewJoinUseCase; private final CreateCrewUseCase createCrewUseCase; private final CrewMemberUseCase crewMemberUseCase; + private final CommandCrewUseCase commandCrewUseCase; @PostMapping public ResponseEntity> createCrew( @RequestBody CreateCrewRequest requestDto, - @RequestAttribute("publicUserId") String userId) { - log.info("action=create_crew user_id={}", userId); + @CurrentUser String currentUserPublicId) { + log.info("action=create_crew user_id={}", currentUserPublicId); - SuccessResponse response = createCrewUseCase.createCrew(requestDto, userId); + SuccessResponse response = createCrewUseCase.createCrew(requestDto, currentUserPublicId); return ResponseEntity.status(HttpStatus.CREATED).body(response); } + @PatchMapping("/{crewPublicId}") + public ResponseEntity> updateCrewInfo( + @PathVariable String crewPublicId, + @RequestBody UpdateCrewInfoRequest requestDto, + @CurrentUser String currentUserPublicId){ + log.info("action=update_crew_info userPublicId={}, crewPublicId={}", currentUserPublicId, crewPublicId); + + SuccessResponse response = commandCrewUseCase.updateCrewInfo(crewPublicId, requestDto, currentUserPublicId); + return ResponseEntity.ok().body(response); + } + + @PatchMapping("/{crewPublicId}/join-rule") + public ResponseEntity> updateCrewJoinRule( + @PathVariable String crewPublicId, + @RequestBody UpdateCrewJoinTypeRequest requestDto, + @CurrentUser String currentUserPublicId){ + log.info("action=update_crew_join_rule userPublicId={}, crewPublicId={}", currentUserPublicId, crewPublicId); + + SuccessResponse response = commandCrewUseCase.updateCrewJoinRule(crewPublicId, requestDto, currentUserPublicId); + return ResponseEntity.ok().body(response); + } + + @DeleteMapping("/{crewPublicId}") + public ResponseEntity> closeCrew( + @PathVariable String crewPublicId, + @CurrentUser String currentUserPublicId){ + log.info("action=delete_crew userPublicId={}, crewPublicId={}", currentUserPublicId, crewPublicId); + + SuccessResponse response = commandCrewUseCase.closeCrew(crewPublicId, currentUserPublicId); + return ResponseEntity.ok().body(response); + } @PostMapping("/{crewPublicId}/join-requests") public ResponseEntity> requestJoin( diff --git a/src/main/java/com/run_us/server/domains/crew/controller/QueryCrewController.java b/src/main/java/com/run_us/server/domains/crew/controller/QueryCrewController.java new file mode 100644 index 00000000..aac1cc4e --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/QueryCrewController.java @@ -0,0 +1,31 @@ +package com.run_us.server.domains.crew.controller; + +import com.run_us.server.domains.crew.controller.model.response.GetCrewHomeResponse; +import com.run_us.server.domains.crew.service.usecase.QueryCrewUseCase; +import com.run_us.server.global.common.SuccessResponse; +import com.run_us.server.global.security.annotation.CurrentUser; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@RestController +@RequestMapping("/crews") +@RequiredArgsConstructor +public class QueryCrewController { + private final QueryCrewUseCase queryCrewUseCase; + + @GetMapping("/{crewPublicId}/home") + public ResponseEntity> getCrewHome( + @PathVariable String crewPublicId, + @CurrentUser String currentUserPublicId) { + log.info("action=get_crew_home crew_public_id={}, user_id={}", crewPublicId, currentUserPublicId); + + SuccessResponse response = queryCrewUseCase.getCrewHome(crewPublicId, currentUserPublicId); + return ResponseEntity.ok().body(response); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewErrorCode.java b/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewErrorCode.java index 478d2cfc..ebc3a93d 100644 --- a/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewErrorCode.java +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewErrorCode.java @@ -19,7 +19,8 @@ public enum CrewErrorCode implements CustomResponseCode { // 403 - RECENTLY_REJECTED_REQUEST("CEH4032","Recently rejected request","Recently rejected request",HttpStatus.FORBIDDEN) + RECENTLY_REJECTED_REQUEST("CEH4032","Recently rejected request","Recently rejected request",HttpStatus.FORBIDDEN), + FORBIDDEN_UPDATE_CREW("CEH4033","Forbidden update crew", "Forbidden update crew",HttpStatus.FORBIDDEN) ; private final String code; diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewHttpResponseCode.java b/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewHttpResponseCode.java index 048912f9..f130708a 100644 --- a/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewHttpResponseCode.java +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/enums/CrewHttpResponseCode.java @@ -7,8 +7,8 @@ @RequiredArgsConstructor public enum CrewHttpResponseCode implements CustomResponseCode { CREW_CREATED("CSH2011", HttpStatus.CREATED, "크루 생성 성공", "크루 생성 성공"), - CREW_HOME_INFO_FETCHED("CSH2002", HttpStatus.OK, "크루 홈 데이터 조회 성공", "크루 홈 데이터 조회 성공"), - CREW_FETCHED("CSH2003", HttpStatus.OK, "크루 정보 조회 성공", "크루 정보 조회 성공"), + CREW_HOME_FETCHED("CSH2002", HttpStatus.OK, "크루 홈 조회 성공", "크루 홈 조회 성공"), + CREW_INFO_PAGE_FETCHED("CSH2003", HttpStatus.OK, "크루 정보 페이지 조회 성공", "크루 정보 페이지 조회 성공"), CREW_UPDATED("CSH2004", HttpStatus.OK, "크루 정보 수정 성공", "크루 정보 수정 성공"), CREW_JOIN_RULE_UPDATED("CSH2005", HttpStatus.OK, "크루 가입 방식 수정 성공", "크루 가입 방식 수정 성공"), CREW_SEARCH_SUCCESS("CSH2006", HttpStatus.OK, "크루 검색 성공", "크루 검색 성공"), diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/request/CreateCrewRequest.java b/src/main/java/com/run_us/server/domains/crew/controller/model/request/CreateCrewRequest.java index 25aab343..350bb463 100644 --- a/src/main/java/com/run_us/server/domains/crew/controller/model/request/CreateCrewRequest.java +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/request/CreateCrewRequest.java @@ -3,6 +3,7 @@ import com.run_us.server.domains.crew.domain.Crew; import com.run_us.server.domains.crew.domain.CrewDescription; import com.run_us.server.domains.crew.domain.CrewMembership; +import com.run_us.server.domains.crew.domain.CrewMonthlyRecord; import com.run_us.server.domains.crew.domain.enums.CrewJoinType; import com.run_us.server.domains.crew.domain.enums.CrewMembershipRole; import com.run_us.server.domains.crew.domain.enums.CrewThemeType; @@ -37,11 +38,17 @@ public Crew toEntity(User creator) { .userId(creator.getId()) .role(CrewMembershipRole.OWNER) .build(); + CrewMonthlyRecord monthlyRecord = CrewMonthlyRecord.builder() + .totalRunningCount(0) + .totalDistance(0) + .totalTime(0) + .build(); return Crew.builder() .crewDescription(description) .joinType(CrewJoinType.valueOf(this.joinType)) .owner(creator) .crewMemberships(List.of(ownerMembership)) + .monthlyRecord(monthlyRecord) .build(); } } diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/request/UpdateCrewInfoRequest.java b/src/main/java/com/run_us/server/domains/crew/controller/model/request/UpdateCrewInfoRequest.java new file mode 100644 index 00000000..bc0aaafd --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/request/UpdateCrewInfoRequest.java @@ -0,0 +1,17 @@ +package com.run_us.server.domains.crew.controller.model.request; + +import com.run_us.server.domains.crew.domain.CrewDescription; +import com.run_us.server.domains.crew.domain.enums.CrewThemeType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UpdateCrewInfoRequest { + private String title; + private String intro; + private String location; + private String profileImageUrl; + private CrewThemeType crewType; +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/request/UpdateCrewJoinTypeRequest.java b/src/main/java/com/run_us/server/domains/crew/controller/model/request/UpdateCrewJoinTypeRequest.java new file mode 100644 index 00000000..a0516e7e --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/request/UpdateCrewJoinTypeRequest.java @@ -0,0 +1,15 @@ +package com.run_us.server.domains.crew.controller.model.request; + +import com.run_us.server.domains.crew.domain.CrewDescription; +import com.run_us.server.domains.crew.domain.enums.CrewJoinType; +import com.run_us.server.domains.crew.domain.enums.CrewThemeType; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UpdateCrewJoinTypeRequest { + private CrewJoinType joinType; + private String joinQuestion; +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/response/CloseCrewResponse.java b/src/main/java/com/run_us/server/domains/crew/controller/model/response/CloseCrewResponse.java new file mode 100644 index 00000000..c76ae9d2 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/response/CloseCrewResponse.java @@ -0,0 +1,25 @@ +package com.run_us.server.domains.crew.controller.model.response; + +import com.run_us.server.domains.crew.domain.Crew; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class CloseCrewResponse { + private String crewPublicId; + + @Builder + private CloseCrewResponse(String crewPublicId) { + this.crewPublicId = crewPublicId; + } + + public static CloseCrewResponse from(Crew crew) { + return CloseCrewResponse.builder() + .crewPublicId(crew.getPublicId()) + .build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/response/CrewThisMonthRecord.java b/src/main/java/com/run_us/server/domains/crew/controller/model/response/CrewThisMonthRecord.java new file mode 100644 index 00000000..966621e5 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/response/CrewThisMonthRecord.java @@ -0,0 +1,27 @@ +package com.run_us.server.domains.crew.controller.model.response; + +import com.run_us.server.domains.crew.domain.CrewMonthlyRecord; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CrewThisMonthRecord { + private Integer totalRunningCount; + private Integer totalDistance; + private Integer totalTime; + + @Builder + CrewThisMonthRecord(Integer totalRunningCount, Integer totalDistance, Integer totalTime){ + this.totalRunningCount = totalRunningCount; + this.totalDistance = totalDistance; + this.totalTime = totalTime; + } + + public static CrewThisMonthRecord from(CrewMonthlyRecord monthlyRecord){ + return CrewThisMonthRecord.builder() + .totalRunningCount(monthlyRecord.getTotalRunningCount()) + .totalDistance(monthlyRecord.getTotalDistance()) + .totalTime(monthlyRecord.getTotalTime()) + .build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/response/GetCrewHomeResponse.java b/src/main/java/com/run_us/server/domains/crew/controller/model/response/GetCrewHomeResponse.java new file mode 100644 index 00000000..ee3fef7c --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/response/GetCrewHomeResponse.java @@ -0,0 +1,87 @@ +package com.run_us.server.domains.crew.controller.model.response; + +import com.run_us.server.domains.crew.domain.Crew; +import com.run_us.server.domains.crew.domain.CrewDescription; +import com.run_us.server.domains.crew.domain.enums.CrewJoinType; +import com.run_us.server.domains.crew.domain.enums.CrewThemeType; +import com.run_us.server.domains.crew.service.model.CrewRunCardInfo; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import java.time.ZonedDateTime; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class GetCrewHomeResponse { + private String crewPublicId; + private String title; + private String profileImg; + private String location; + private String intro; + private CrewJoinType joinType; + private String joinQuestion; + private CrewThemeType crewType; + private Integer memberCount; + private ZonedDateTime createdAt; + private SimpleUserInfo crewOwner; + private Boolean existNewJoinRequest; + private CrewThisMonthRecord thisMonthRecord; + private RunCardInfo regularRunning; + private RunCardInfo irregularRunning; + + @Builder + public GetCrewHomeResponse( + String crewPublicId, String title, String profileImg, String location, String intro, + CrewJoinType joinType, String joinQuestion, CrewThemeType crewType, + Integer memberCount, ZonedDateTime createdAt, SimpleUserInfo crewOwner, + Boolean existNewJoinRequest, CrewThisMonthRecord thisMonthRecord, + RunCardInfo regularRunning, RunCardInfo irregularRunning + ) { + this.crewPublicId = crewPublicId; + this.title = title; + this.profileImg = profileImg; + this.location = location; + this.intro = intro; + this.joinType = joinType; + this.joinQuestion = joinQuestion; + this.crewType = crewType; + this.memberCount = memberCount; + this.createdAt = createdAt; + this.crewOwner = crewOwner; + this.existNewJoinRequest = existNewJoinRequest; + this.thisMonthRecord = thisMonthRecord; + this.regularRunning = regularRunning; + this.irregularRunning = irregularRunning; + } + + + public static GetCrewHomeResponse from(Crew crew, boolean existNewJoinRequest, CrewRunCardInfo cardRunInfo) { + CrewDescription description = crew.getCrewDescription(); + + GetCrewHomeResponseBuilder builder = GetCrewHomeResponse.builder() + .crewPublicId(crew.getPublicId()) + .title(description.getTitle()) + .profileImg(description.getProfileImageUrl()) + .location(description.getLocation()) + .intro(description.getIntro()) + .joinType(crew.getJoinType()) + .joinQuestion(description.getJoinQuestion()) + .crewType(description.getThemeType()) + .memberCount(crew.getMemberCount()) + .createdAt(crew.getCreatedAt()) + + .crewOwner(SimpleUserInfo.from(crew.getOwner())) + .existNewJoinRequest(existNewJoinRequest) + .thisMonthRecord(CrewThisMonthRecord.from(crew.getMonthlyRecord())); + + if (cardRunInfo.getIrregularRunCard() != null) { + builder.irregularRunning(cardRunInfo.getIrregularRunCard()); + } + if (cardRunInfo.getRegularRunCard() != null) { + builder.regularRunning(cardRunInfo.getRegularRunCard()); + } + + return builder.build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/response/RunCardInfo.java b/src/main/java/com/run_us/server/domains/crew/controller/model/response/RunCardInfo.java new file mode 100644 index 00000000..3ea5f893 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/response/RunCardInfo.java @@ -0,0 +1,55 @@ +package com.run_us.server.domains.crew.controller.model.response; + +import com.run_us.server.domains.running.run.domain.Run; +import com.run_us.server.domains.running.run.domain.RunPace; +import com.run_us.server.domains.running.run.domain.RunningPreview; +import com.run_us.server.domains.user.domain.User; +import com.run_us.server.global.common.GlobalConst; +import lombok.Builder; +import lombok.Getter; + +import java.time.format.DateTimeFormatter; +import java.util.List; + +@Getter +public class RunCardInfo { + private String runningPublicId; + private String topMessage; + private String title; + private String description; + private String startAt; + private List paceList; + private Integer participantCount; + private SimpleUserInfo createdBy; + + + @Builder + private RunCardInfo( + String runningPublicId, + String topMessage, String title, String description, String startAt, + List paceList, Integer participantCount, SimpleUserInfo createdBy) { + this.runningPublicId = runningPublicId; + this.topMessage = topMessage; + this.title = title; + this.description = description; + this.startAt = startAt; + this.paceList = paceList; + this.participantCount = participantCount; + this.createdBy = createdBy; + } + + public static RunCardInfo from(Run run, String topMessage, User createdUser) { + RunningPreview preview = run.getPreview(); + + return RunCardInfo.builder() + .runningPublicId(run.getPublicId()) + .topMessage(topMessage) + .title(preview.getTitle()) + .description(preview.getDescription()) + .startAt(preview.getBeginTime().format(DateTimeFormatter.ofPattern(GlobalConst.TIME_FORMAT_PATTERN))) + .paceList(run.getPaceCategories()) + .createdBy(SimpleUserInfo.from(createdUser)) + .build(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/response/SimpleUserInfo.java b/src/main/java/com/run_us/server/domains/crew/controller/model/response/SimpleUserInfo.java new file mode 100644 index 00000000..50c973cc --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/response/SimpleUserInfo.java @@ -0,0 +1,36 @@ +package com.run_us.server.domains.crew.controller.model.response; + +import com.run_us.server.domains.crew.controller.model.enums.CrewErrorCode; +import com.run_us.server.domains.crew.controller.model.enums.CrewException; +import com.run_us.server.domains.user.domain.Profile; +import com.run_us.server.domains.user.domain.User; +import com.run_us.server.domains.user.exception.UserErrorCode; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class SimpleUserInfo { + private String userPublicId; + private String profileImageUrl; + private String nickname; + + @Builder + public SimpleUserInfo(String userPublicId, String profileImageUrl, String nickname) { + this.userPublicId = userPublicId; + this.profileImageUrl = profileImageUrl; + this.nickname = nickname; + } + + public static SimpleUserInfo from(User user) { + Profile profile = user.getProfile(); + if(profile == null){ + throw new CrewException(UserErrorCode.GET_USER_PROFILE_FAILED); + } + + return SimpleUserInfo.builder() + .userPublicId(user.getPublicId()) + .profileImageUrl(profile.getImgUrl()) + .nickname(profile.getNickname()) + .build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/response/UpdateCrewInfoResponse.java b/src/main/java/com/run_us/server/domains/crew/controller/model/response/UpdateCrewInfoResponse.java new file mode 100644 index 00000000..94e3b613 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/response/UpdateCrewInfoResponse.java @@ -0,0 +1,23 @@ +package com.run_us.server.domains.crew.controller.model.response; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UpdateCrewInfoResponse { + private String crewPublicId; + + @Builder + public UpdateCrewInfoResponse(String crewPublicId) { + this.crewPublicId = crewPublicId; + } + + public static UpdateCrewInfoResponse from(String crewPublicId) { + return UpdateCrewInfoResponse.builder() + .crewPublicId(crewPublicId) + .build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/controller/model/response/UpdateCrewJoinRuleResponse.java b/src/main/java/com/run_us/server/domains/crew/controller/model/response/UpdateCrewJoinRuleResponse.java new file mode 100644 index 00000000..16133201 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/controller/model/response/UpdateCrewJoinRuleResponse.java @@ -0,0 +1,31 @@ +package com.run_us.server.domains.crew.controller.model.response; + +import com.run_us.server.domains.crew.domain.Crew; +import com.run_us.server.domains.crew.domain.enums.CrewJoinType; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UpdateCrewJoinRuleResponse { + private String crewPublicId; + private CrewJoinType joinType; + private String joinQuestion; + + @Builder + public UpdateCrewJoinRuleResponse(String crewPublicId, CrewJoinType joinType, String joinQuestion) { + this.crewPublicId = crewPublicId; + this.joinType = joinType; + this.joinQuestion = joinQuestion; + } + + public static UpdateCrewJoinRuleResponse from(Crew crew) { + return UpdateCrewJoinRuleResponse.builder() + .crewPublicId(crew.getPublicId()) + .joinType(crew.getJoinType()) + .joinQuestion(crew.getCrewDescription().getJoinQuestion()) + .build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/domain/Crew.java b/src/main/java/com/run_us/server/domains/crew/domain/Crew.java index f286bb87..e8a82a01 100644 --- a/src/main/java/com/run_us/server/domains/crew/domain/Crew.java +++ b/src/main/java/com/run_us/server/domains/crew/domain/Crew.java @@ -1,6 +1,5 @@ package com.run_us.server.domains.crew.domain; -import com.run_us.server.domains.crew.domain.enums.CrewJoinRequestStatus; import com.run_us.server.domains.crew.domain.enums.CrewJoinType; import com.run_us.server.domains.crew.domain.enums.CrewStatus; import com.run_us.server.domains.user.domain.User; @@ -46,6 +45,9 @@ public class Crew extends DateAudit { @Embedded private CrewDescription crewDescription; + @Embedded + private CrewMonthlyRecord monthlyRecord; + @ElementCollection @CollectionTable(name = "crew_memberships", joinColumns = @JoinColumn(name="crew_id")) private List crewMemberships = new ArrayList<>(); @@ -75,6 +77,15 @@ public void removeMember(Integer userId) { this.memberCount--; } + public boolean isOwner(Integer userId) { + return this.owner.getId().equals(userId); + } + + public void updateCrewInfo(CrewDescription crewDescription) { + this.crewDescription = crewDescription; + } + + @Override public void prePersist() { this.publicId = TSID.Factory.getTsid().toString(); @@ -86,7 +97,8 @@ public Crew( User owner, CrewJoinType joinType, CrewDescription crewDescription, - List crewMemberships + List crewMemberships, + CrewMonthlyRecord monthlyRecord ){ this.owner = owner; this.joinType = joinType; @@ -94,5 +106,15 @@ public Crew( this.memberCount = 1; this.status = CrewStatus.ACTIVE; this.crewMemberships = crewMemberships; + this.monthlyRecord = monthlyRecord; + } + + public void updateJoinRule(CrewJoinType joinType, String joinQuestion) { + this.joinType = joinType; + this.getCrewDescription().updateJoinQuestion(joinQuestion); + } + + public void close() { + this.status = CrewStatus.SUSPENDED; } } diff --git a/src/main/java/com/run_us/server/domains/crew/domain/CrewDescription.java b/src/main/java/com/run_us/server/domains/crew/domain/CrewDescription.java index 2c0517f5..dc2f45c7 100644 --- a/src/main/java/com/run_us/server/domains/crew/domain/CrewDescription.java +++ b/src/main/java/com/run_us/server/domains/crew/domain/CrewDescription.java @@ -74,4 +74,8 @@ public boolean equals(Object obj) { public int hashCode() { return Objects.hash(this.title, this.profileImageUrl, this.location, this.intro, this.themeType, this.joinQuestion); } + + public void updateJoinQuestion(String joinQuestion) { + this.joinQuestion = joinQuestion; + } } diff --git a/src/main/java/com/run_us/server/domains/crew/domain/CrewMonthlyRecord.java b/src/main/java/com/run_us/server/domains/crew/domain/CrewMonthlyRecord.java new file mode 100644 index 00000000..a3291702 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/domain/CrewMonthlyRecord.java @@ -0,0 +1,25 @@ +package com.run_us.server.domains.crew.domain; + +import lombok.*; + +@ToString +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class CrewMonthlyRecord { + private int totalRunningCount; + private int totalDistance; + private int totalTime; + + @Builder + CrewMonthlyRecord(int totalRunningCount, int totalDistance, int totalTime){ + this.totalRunningCount = totalRunningCount; + this.totalDistance = totalDistance; + this.totalTime = totalTime; + } + + public void addRecord(int addDistance, int addTime){ + this.totalRunningCount++; + this.totalDistance += addDistance; + this.totalTime += addTime; + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/exception/CrewException.java b/src/main/java/com/run_us/server/domains/crew/exception/CrewException.java new file mode 100644 index 00000000..08b49c1a --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/exception/CrewException.java @@ -0,0 +1,19 @@ +package com.run_us.server.domains.crew.exception; + +import com.run_us.server.global.exception.BusinessException; +import com.run_us.server.global.exception.code.CustomResponseCode; + +public class CrewException extends BusinessException { + + protected CrewException(CustomResponseCode errorCode, String logMessage) { + super(errorCode, logMessage); + } + + public CrewException(CustomResponseCode errorCode) { + super(errorCode); + } + + public static CrewException of(CustomResponseCode errorCode) { + return new CrewException(errorCode); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/repository/CrewJoinRequestRepository.java b/src/main/java/com/run_us/server/domains/crew/repository/CrewJoinRequestRepository.java index 1e25fb9b..82071d46 100644 --- a/src/main/java/com/run_us/server/domains/crew/repository/CrewJoinRequestRepository.java +++ b/src/main/java/com/run_us/server/domains/crew/repository/CrewJoinRequestRepository.java @@ -1,6 +1,7 @@ package com.run_us.server.domains.crew.repository; import com.run_us.server.domains.crew.domain.CrewJoinRequest; +import com.run_us.server.domains.crew.domain.enums.CrewJoinRequestStatus; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; @@ -25,4 +26,6 @@ Optional findByCrewIdAndUserIdAndAfterRequestedAt( Integer userId, ZonedDateTime recentDate ); + + boolean existsByCrewIdAndStatus(Integer crewId, CrewJoinRequestStatus status); } diff --git a/src/main/java/com/run_us/server/domains/crew/service/CommandCrewService.java b/src/main/java/com/run_us/server/domains/crew/service/CommandCrewService.java new file mode 100644 index 00000000..ee6a4cbd --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/service/CommandCrewService.java @@ -0,0 +1,43 @@ +package com.run_us.server.domains.crew.service; + +import com.run_us.server.domains.crew.controller.model.request.CreateCrewRequest; +import com.run_us.server.domains.crew.controller.model.request.UpdateCrewJoinTypeRequest; +import com.run_us.server.domains.crew.domain.Crew; +import com.run_us.server.domains.crew.domain.CrewDescription; +import com.run_us.server.domains.crew.repository.CrewRepository; +import com.run_us.server.domains.crew.service.model.UpdateCrewInfo; +import com.run_us.server.domains.user.domain.User; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CommandCrewService { + + private final CrewRepository crewRepository; + private final CrewValidator crewValidator; + + public Crew saveCrew(CreateCrewRequest requestDto, User creator) { + Crew crew = requestDto.toEntity(creator); + return crewRepository.save(crew); + } + + public void updateCrewInfo(UpdateCrewInfo requestDto, Crew crew, Integer userId) { + crewValidator.validateCrewOwner(crew, userId); + + CrewDescription newCrewDescription = requestDto.to(crew.getCrewDescription()); + crew.updateCrewInfo(newCrewDescription); + } + + public void updateCrewJoinRule(UpdateCrewJoinTypeRequest requestDto, Crew crew, Integer userId) { + crewValidator.validateCrewOwner(crew, userId); + + crew.updateJoinRule(requestDto.getJoinType(), requestDto.getJoinQuestion()); + } + + public void closeCrew(Crew crew, Integer userId) { + crewValidator.validateCrewOwner(crew, userId); + + crew.close(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/service/CrewCommandService.java b/src/main/java/com/run_us/server/domains/crew/service/CrewCommandService.java deleted file mode 100644 index 46943739..00000000 --- a/src/main/java/com/run_us/server/domains/crew/service/CrewCommandService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.run_us.server.domains.crew.service; - -import com.run_us.server.domains.crew.controller.model.request.CreateCrewRequest; -import com.run_us.server.domains.crew.domain.Crew; -import com.run_us.server.domains.crew.repository.CrewRepository; -import com.run_us.server.domains.user.domain.User; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class CrewCommandService { - - private final CrewRepository crewRepository; - - public Crew saveCrew(CreateCrewRequest requestDto, User creator) { - Crew crew = requestDto.toEntity(creator); - return crewRepository.save(crew); - } -} diff --git a/src/main/java/com/run_us/server/domains/crew/service/CrewService.java b/src/main/java/com/run_us/server/domains/crew/service/CrewService.java index 62a01b81..27b36e15 100644 --- a/src/main/java/com/run_us/server/domains/crew/service/CrewService.java +++ b/src/main/java/com/run_us/server/domains/crew/service/CrewService.java @@ -94,4 +94,9 @@ public void removeMember(Crew crew, Integer targetUserId) { log.debug("action=remove_member_end crewPublicId={} targetUserId={}", crew.getPublicId(), targetUserId); } + + @Transactional(readOnly = true) + public boolean existNewJoinRequest(Integer crewId) { + return crewJoinRequestRepository.existsByCrewIdAndStatus(crewId, CrewJoinRequestStatus.WAITING); + } } \ No newline at end of file diff --git a/src/main/java/com/run_us/server/domains/crew/service/CrewValidator.java b/src/main/java/com/run_us/server/domains/crew/service/CrewValidator.java index 158e0a0d..4ea1327c 100644 --- a/src/main/java/com/run_us/server/domains/crew/service/CrewValidator.java +++ b/src/main/java/com/run_us/server/domains/crew/service/CrewValidator.java @@ -92,4 +92,16 @@ public void validateCanFetchMembers(Integer userId, Crew crew) { throw new CrewException(CrewErrorCode.SUSPENDED_CREW); } } + + public void validateCrewOwner(Crew crew, Integer userId) { + if (!crew.isOwner(userId)) { + throw new CrewException(CrewErrorCode.FORBIDDEN_UPDATE_CREW); + } + } + + public void validateCrewMember(Crew crew, Integer userId) { + if (!crew.isMember(userId)) { + throw new CrewException(CrewErrorCode.NOT_CREW_MEMBER); + } + } } \ No newline at end of file diff --git a/src/main/java/com/run_us/server/domains/crew/service/model/CrewRunCardInfo.java b/src/main/java/com/run_us/server/domains/crew/service/model/CrewRunCardInfo.java new file mode 100644 index 00000000..65bd5ff9 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/service/model/CrewRunCardInfo.java @@ -0,0 +1,17 @@ +package com.run_us.server.domains.crew.service.model; + +import com.run_us.server.domains.crew.controller.model.response.RunCardInfo; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class CrewRunCardInfo { + RunCardInfo regularRunCard; + RunCardInfo irregularRunCard; + + @Builder + public CrewRunCardInfo(RunCardInfo regularRunCard, RunCardInfo irregularRunCard) { + this.regularRunCard = regularRunCard; + this.irregularRunCard = irregularRunCard; + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/service/model/UpdateCrewInfo.java b/src/main/java/com/run_us/server/domains/crew/service/model/UpdateCrewInfo.java new file mode 100644 index 00000000..b513931d --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/service/model/UpdateCrewInfo.java @@ -0,0 +1,49 @@ +package com.run_us.server.domains.crew.service.model; + +import com.run_us.server.domains.crew.controller.model.request.UpdateCrewInfoRequest; +import com.run_us.server.domains.crew.domain.CrewDescription; +import com.run_us.server.domains.crew.domain.enums.CrewThemeType; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class UpdateCrewInfo { + private String title; + private String intro; + private String location; + private String profileImageUrl; + private CrewThemeType crewType; + + @Builder + UpdateCrewInfo(String title, String intro, String location, String profileImageUrl, CrewThemeType crewType){ + this.title = title; + this.intro = intro; + this.location = location; + this.profileImageUrl = profileImageUrl; + this.crewType = crewType; + } + + public static UpdateCrewInfo from(UpdateCrewInfoRequest requestDto) { + return UpdateCrewInfo.builder() + .title(requestDto.getTitle()) + .intro(requestDto.getIntro()) + .location(requestDto.getLocation()) + .profileImageUrl(requestDto.getProfileImageUrl()) + .crewType(requestDto.getCrewType()) + .build(); + } + + public CrewDescription to(CrewDescription old) { + return CrewDescription.builder() + .title(this.title) + .intro(this.intro) + .location(this.location) + .profileImageUrl(this.profileImageUrl) + .themeType(this.crewType) + .joinQuestion(old.getJoinQuestion()) + .build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/service/usecase/CommandCrewUseCase.java b/src/main/java/com/run_us/server/domains/crew/service/usecase/CommandCrewUseCase.java new file mode 100644 index 00000000..8e927594 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/service/usecase/CommandCrewUseCase.java @@ -0,0 +1,16 @@ +package com.run_us.server.domains.crew.service.usecase; + +import com.run_us.server.domains.crew.controller.model.request.UpdateCrewInfoRequest; +import com.run_us.server.domains.crew.controller.model.request.UpdateCrewJoinTypeRequest; +import com.run_us.server.domains.crew.controller.model.response.CloseCrewResponse; +import com.run_us.server.domains.crew.controller.model.response.UpdateCrewInfoResponse; +import com.run_us.server.domains.crew.controller.model.response.UpdateCrewJoinRuleResponse; +import com.run_us.server.global.common.SuccessResponse; + +public interface CommandCrewUseCase { + SuccessResponse updateCrewInfo(String crewPublicId, UpdateCrewInfoRequest requestDto, String userPublicId); + + SuccessResponse updateCrewJoinRule(String crewPublicId, UpdateCrewJoinTypeRequest requestDto, String userPublicId); + + SuccessResponse closeCrew(String crewPublicId, String userPublicId); +} diff --git a/src/main/java/com/run_us/server/domains/crew/service/usecase/CommandCrewUseCaseImpl.java b/src/main/java/com/run_us/server/domains/crew/service/usecase/CommandCrewUseCaseImpl.java new file mode 100644 index 00000000..5f82cae7 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/service/usecase/CommandCrewUseCaseImpl.java @@ -0,0 +1,57 @@ +package com.run_us.server.domains.crew.service.usecase; + +import com.run_us.server.domains.crew.controller.model.enums.CrewHttpResponseCode; +import com.run_us.server.domains.crew.controller.model.request.UpdateCrewInfoRequest; +import com.run_us.server.domains.crew.controller.model.request.UpdateCrewJoinTypeRequest; +import com.run_us.server.domains.crew.controller.model.response.CloseCrewResponse; +import com.run_us.server.domains.crew.controller.model.response.UpdateCrewInfoResponse; +import com.run_us.server.domains.crew.controller.model.response.UpdateCrewJoinRuleResponse; +import com.run_us.server.domains.crew.domain.Crew; +import com.run_us.server.domains.crew.service.CommandCrewService; +import com.run_us.server.domains.crew.service.CrewService; +import com.run_us.server.domains.crew.service.model.UpdateCrewInfo; +import com.run_us.server.domains.user.domain.UserPrincipal; +import com.run_us.server.domains.user.service.resolver.UserIdResolver; +import com.run_us.server.global.common.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class CommandCrewUseCaseImpl implements CommandCrewUseCase { + private final CrewService crewService; + private final CommandCrewService commandCrewService; + private final UserIdResolver userIdResolver; + + @Override + @Transactional + public SuccessResponse updateCrewInfo(String crewPublicId, UpdateCrewInfoRequest requestDto, String userPublicId) { + UserPrincipal userPrincipal = userIdResolver.resolve(userPublicId); + + Crew crew = crewService.getCrewByPublicId(crewPublicId); + commandCrewService.updateCrewInfo(UpdateCrewInfo.from(requestDto), crew, userPrincipal.getInternalId()); + return SuccessResponse.of(CrewHttpResponseCode.CREW_UPDATED, UpdateCrewInfoResponse.from(crew.getPublicId())); + } + + @Override + @Transactional + public SuccessResponse updateCrewJoinRule(String crewPublicId, UpdateCrewJoinTypeRequest requestDto, String userPublicId) { + UserPrincipal userPrincipal = userIdResolver.resolve(userPublicId); + + Crew crew = crewService.getCrewByPublicId(crewPublicId); + commandCrewService.updateCrewJoinRule(requestDto, crew, userPrincipal.getInternalId()); + return SuccessResponse.of(CrewHttpResponseCode.CREW_JOIN_RULE_UPDATED, UpdateCrewJoinRuleResponse.from(crew)); + } + + @Override + @Transactional + public SuccessResponse closeCrew(String crewPublicId, String userPublicId) { + UserPrincipal userPrincipal = userIdResolver.resolve(userPublicId); + + Crew crew = crewService.getCrewByPublicId(crewPublicId); + commandCrewService.closeCrew(crew, userPrincipal.getInternalId()); + return SuccessResponse.of(CrewHttpResponseCode.CREW_CLOSE_SUCCESS, CloseCrewResponse.from(crew)); + } +} diff --git a/src/main/java/com/run_us/server/domains/crew/service/usecase/CreateCrewUseCaseImpl.java b/src/main/java/com/run_us/server/domains/crew/service/usecase/CreateCrewUseCaseImpl.java index d35e2d20..686fbf06 100644 --- a/src/main/java/com/run_us/server/domains/crew/service/usecase/CreateCrewUseCaseImpl.java +++ b/src/main/java/com/run_us/server/domains/crew/service/usecase/CreateCrewUseCaseImpl.java @@ -4,7 +4,7 @@ import com.run_us.server.domains.crew.controller.model.request.CreateCrewRequest; import com.run_us.server.domains.crew.controller.model.response.CreateCrewResponse; import com.run_us.server.domains.crew.domain.Crew; -import com.run_us.server.domains.crew.service.CrewCommandService; +import com.run_us.server.domains.crew.service.CommandCrewService; import com.run_us.server.domains.user.domain.User; import com.run_us.server.domains.user.service.UserService; import com.run_us.server.global.common.SuccessResponse; @@ -18,13 +18,13 @@ public class CreateCrewUseCaseImpl implements CreateCrewUseCase { private final UserService userService; - private final CrewCommandService crewCommandService; + private final CommandCrewService commandCrewService; @Override @Transactional public SuccessResponse createCrew(CreateCrewRequest requestDto, String creatorId) { User creator = userService.getUserByPublicId(creatorId); - Crew crew = crewCommandService.saveCrew(requestDto, creator); + Crew crew = commandCrewService.saveCrew(requestDto, creator); return SuccessResponse.of(CrewHttpResponseCode.CREW_CREATED, CreateCrewResponse.from(crew)); } diff --git a/src/main/java/com/run_us/server/domains/crew/service/usecase/QueryCrewUseCase.java b/src/main/java/com/run_us/server/domains/crew/service/usecase/QueryCrewUseCase.java new file mode 100644 index 00000000..405130a3 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/service/usecase/QueryCrewUseCase.java @@ -0,0 +1,8 @@ +package com.run_us.server.domains.crew.service.usecase; + +import com.run_us.server.domains.crew.controller.model.response.GetCrewHomeResponse; +import com.run_us.server.global.common.SuccessResponse; + +public interface QueryCrewUseCase { + SuccessResponse getCrewHome(String crewPublicId, String userPublicId); +} diff --git a/src/main/java/com/run_us/server/domains/crew/service/usecase/QueryCrewUseCaseImpl.java b/src/main/java/com/run_us/server/domains/crew/service/usecase/QueryCrewUseCaseImpl.java new file mode 100644 index 00000000..4f1ec47a --- /dev/null +++ b/src/main/java/com/run_us/server/domains/crew/service/usecase/QueryCrewUseCaseImpl.java @@ -0,0 +1,71 @@ +package com.run_us.server.domains.crew.service.usecase; +import com.run_us.server.domains.crew.controller.model.enums.CrewHttpResponseCode; +import com.run_us.server.domains.crew.controller.model.response.GetCrewHomeResponse; +import com.run_us.server.domains.crew.controller.model.response.RunCardInfo; +import com.run_us.server.domains.crew.domain.Crew; +import com.run_us.server.domains.crew.service.CrewService; +import com.run_us.server.domains.crew.service.CrewValidator; +import com.run_us.server.domains.crew.service.model.CrewRunCardInfo; +import com.run_us.server.domains.running.run.domain.Run; +import com.run_us.server.domains.running.run.service.RunQueryService; +import com.run_us.server.domains.running.run.service.model.GetCrewCardRun; +import com.run_us.server.domains.running.run.service.strategy.RunTopMessageContext; +import com.run_us.server.domains.running.run.service.strategy.TimePlaceMessage; +import com.run_us.server.domains.user.domain.User; +import com.run_us.server.domains.user.domain.UserPrincipal; +import com.run_us.server.domains.user.service.UserService; +import com.run_us.server.domains.user.service.resolver.UserIdResolver; +import com.run_us.server.global.common.SuccessResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class QueryCrewUseCaseImpl implements QueryCrewUseCase { + private final CrewService crewService; + private final RunQueryService runQueryService; + private final UserService userService; + private final UserIdResolver userIdResolver; + private final CrewValidator crewValidator; + + @Override + public SuccessResponse getCrewHome(String crewPublicId, String userPublicId) { + UserPrincipal userPrincipal = userIdResolver.resolve(userPublicId); + Crew crew = crewService.getCrewByPublicId(crewPublicId); + crewValidator.validateCrewMember(crew, userPrincipal.getInternalId()); + + boolean existNewJoinRequest = crewService.existNewJoinRequest(crew.getId()); + + CrewRunCardInfo crewRunCardInfo = getCrewRunCardInfo(crew); + + return SuccessResponse.of(CrewHttpResponseCode.CREW_HOME_FETCHED, GetCrewHomeResponse.from(crew, existNewJoinRequest, crewRunCardInfo)); + } + + private CrewRunCardInfo getCrewRunCardInfo(Crew crew) { + GetCrewCardRun crewCardRun = runQueryService.getCrewCardRun(crew.getId()); + + CrewRunCardInfo.CrewRunCardInfoBuilder crewCardRunBuilder = CrewRunCardInfo.builder(); + + Run regularRun = crewCardRun.getRegularRun(); + if (regularRun != null) { + RunCardInfo regularRunCard = getRunCardInfo(regularRun); + crewCardRunBuilder.regularRunCard(regularRunCard); + } + + Run irregularRun = crewCardRun.getIrregularRun(); + if(irregularRun != null) { + RunCardInfo irregularRunCard = getRunCardInfo(irregularRun); + crewCardRunBuilder.irregularRunCard(irregularRunCard); + } + + return crewCardRunBuilder.build(); + } + + private RunCardInfo getRunCardInfo(Run run) { + User runHost = userService.getUserByInternalId(run.getHostId()); + return RunCardInfo.from(run, RunTopMessageContext.getMessage(new TimePlaceMessage(run)), runHost); + } + +} \ No newline at end of file diff --git a/src/main/java/com/run_us/server/domains/running/run/domain/RunType.java b/src/main/java/com/run_us/server/domains/running/run/domain/RunType.java new file mode 100644 index 00000000..9e3ce4a7 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/domain/RunType.java @@ -0,0 +1,8 @@ +package com.run_us.server.domains.running.run.domain; + +public enum RunType { + SINGLE, + GROUP_REGULAR, + GROUP_IRREGULAR, + CUSTOM +} diff --git a/src/main/java/com/run_us/server/domains/running/run/domain/RunningPreview.java b/src/main/java/com/run_us/server/domains/running/run/domain/RunningPreview.java index b63e58c3..cccff163 100644 --- a/src/main/java/com/run_us/server/domains/running/run/domain/RunningPreview.java +++ b/src/main/java/com/run_us/server/domains/running/run/domain/RunningPreview.java @@ -16,6 +16,7 @@ public class RunningPreview implements Serializable { private String title; private String description; + private RunType type; private String meetingPoint; private SessionAccessLevel accessLevel = SessionAccessLevel.ALLOW_ALL; private ZonedDateTime beginTime; @@ -24,16 +25,19 @@ public class RunningPreview implements Serializable { public RunningPreview( String title, String description, + RunType type, String meetingPoint, SessionAccessLevel accessLevel, ZonedDateTime beginTime) { this.title = title; this.description = description; + this.type = type; this.meetingPoint = meetingPoint; this.accessLevel = accessLevel; this.beginTime = beginTime; } + // TODO : run type 추가 public static RunningPreview from(RunCreateDto runCreateDto) { return RunningPreview.builder() .title(runCreateDto.getTitle()) diff --git a/src/main/java/com/run_us/server/domains/running/run/repository/RunRepository.java b/src/main/java/com/run_us/server/domains/running/run/repository/RunRepository.java index 7ce811ef..c03eae18 100644 --- a/src/main/java/com/run_us/server/domains/running/run/repository/RunRepository.java +++ b/src/main/java/com/run_us/server/domains/running/run/repository/RunRepository.java @@ -1,5 +1,7 @@ package com.run_us.server.domains.running.run.repository; +import com.run_us.server.domains.running.run.domain.RunStatus; +import com.run_us.server.domains.running.run.domain.RunType; import com.run_us.server.domains.running.run.domain.SessionAccessLevel; import com.run_us.server.domains.running.run.domain.Run; import com.run_us.server.domains.running.run.service.model.JoinedRunPreviewResponse; @@ -8,6 +10,7 @@ import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -52,4 +55,12 @@ public interface RunRepository extends JpaRepository { + "WHERE r.crewId = :crewId and r.preview.accessLevel = :accessLevel" ) Slice findAllByCrewIdAndAccessLevel(Integer crewId, SessionAccessLevel accessLevel, PageRequest pageRequest); + + @Query( + "SELECT r " + + "FROM Run r " + + "WHERE r.crewId = :crewId AND r.status = :status AND r.preview.type = :type " + + "ORDER BY r.preview.beginTime ASC" + ) + Optional findFirstForCrewCard(@Param("crewId") Integer crewId, @Param("type") RunType type, @Param("status") RunStatus status); } diff --git a/src/main/java/com/run_us/server/domains/running/run/service/RunQueryService.java b/src/main/java/com/run_us/server/domains/running/run/service/RunQueryService.java index ddce0782..2368952b 100644 --- a/src/main/java/com/run_us/server/domains/running/run/service/RunQueryService.java +++ b/src/main/java/com/run_us/server/domains/running/run/service/RunQueryService.java @@ -3,8 +3,11 @@ import com.run_us.server.domains.running.common.RunningErrorCode; import com.run_us.server.domains.running.common.RunningException; import com.run_us.server.domains.running.run.domain.Run; +import com.run_us.server.domains.running.run.domain.RunStatus; +import com.run_us.server.domains.running.run.domain.RunType; import com.run_us.server.domains.running.run.domain.SessionAccessLevel; import com.run_us.server.domains.running.run.repository.RunRepository; +import com.run_us.server.domains.running.run.service.model.GetCrewCardRun; import com.run_us.server.domains.running.run.service.model.JoinedRunPreviewResponse; import com.run_us.server.domains.running.run.service.model.GetRunPreviewResponse; import lombok.RequiredArgsConstructor; @@ -15,6 +18,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; @Component @@ -69,4 +73,11 @@ private void updateJoinedRunPreviewWithPaceTypes(List runs, Map regularRunOp = runRepository.findFirstForCrewCard(crewId, RunType.GROUP_REGULAR, RunStatus.WAITING); + Optional irregularRunOp = runRepository.findFirstForCrewCard(crewId, RunType.GROUP_IRREGULAR, RunStatus.WAITING); + + return GetCrewCardRun.from(regularRunOp.orElse(null), irregularRunOp.orElse(null)); + } } diff --git a/src/main/java/com/run_us/server/domains/running/run/service/model/GetCrewCardRun.java b/src/main/java/com/run_us/server/domains/running/run/service/model/GetCrewCardRun.java new file mode 100644 index 00000000..2b6a61ce --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/service/model/GetCrewCardRun.java @@ -0,0 +1,31 @@ +package com.run_us.server.domains.running.run.service.model; + +import com.run_us.server.domains.running.run.domain.Run; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; + +@Getter +public class GetCrewCardRun { + Run regularRun; + Run irregularRun; + + @Builder(access = AccessLevel.PRIVATE) + public GetCrewCardRun(Run regularRun, Run irregularRun) { + this.regularRun = regularRun; + this.irregularRun = irregularRun; + } + + public static GetCrewCardRun from(Run regularRun, Run irregularRun) { + GetCrewCardRunBuilder builder = GetCrewCardRun.builder(); + + if (regularRun != null) { + builder.regularRun(regularRun); + } + if (irregularRun != null) { + builder.irregularRun(irregularRun); + } + + return builder.build(); + } +} diff --git a/src/main/java/com/run_us/server/domains/running/run/service/strategy/IrregularRunOnlyCrewMessage.java b/src/main/java/com/run_us/server/domains/running/run/service/strategy/IrregularRunOnlyCrewMessage.java new file mode 100644 index 00000000..520a1ec0 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/service/strategy/IrregularRunOnlyCrewMessage.java @@ -0,0 +1,23 @@ +package com.run_us.server.domains.running.run.service.strategy; + +import com.run_us.server.domains.crew.domain.Crew; +import com.run_us.server.domains.running.run.domain.Run; + +import java.time.format.DateTimeFormatter; + +public class IrregularRunOnlyCrewMessage implements RunTopMessageStrategy { + private final Crew crew; + + public IrregularRunOnlyCrewMessage(Crew crew) { + this.crew = crew; + } + + @Override + public String createMessage() { + String message = "\'" + + crew.getCrewDescription().getTitle() + + "\'번개런"; + + return message; + } +} diff --git a/src/main/java/com/run_us/server/domains/running/run/service/strategy/RegularRunAllowAllMessage.java b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RegularRunAllowAllMessage.java new file mode 100644 index 00000000..496fa86d --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RegularRunAllowAllMessage.java @@ -0,0 +1,8 @@ +package com.run_us.server.domains.running.run.service.strategy; + +public class RegularRunAllowAllMessage implements RunTopMessageStrategy { + @Override + public String createMessage() { + return "게스트 모집"; + } +} diff --git a/src/main/java/com/run_us/server/domains/running/run/service/strategy/RegularRunOnlyCrewMessage.java b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RegularRunOnlyCrewMessage.java new file mode 100644 index 00000000..7383b270 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RegularRunOnlyCrewMessage.java @@ -0,0 +1,20 @@ +package com.run_us.server.domains.running.run.service.strategy; + +import com.run_us.server.domains.crew.domain.Crew; + +public class RegularRunOnlyCrewMessage implements RunTopMessageStrategy { + private final Crew crew; + + public RegularRunOnlyCrewMessage(Crew crew) { + this.crew = crew; + } + + @Override + public String createMessage() { + String message = "\'" + + crew.getCrewDescription().getTitle() + + "\'정기런"; + + return message; + } +} diff --git a/src/main/java/com/run_us/server/domains/running/run/service/strategy/RunTopMessageContext.java b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RunTopMessageContext.java new file mode 100644 index 00000000..e8994013 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RunTopMessageContext.java @@ -0,0 +1,8 @@ +package com.run_us.server.domains.running.run.service.strategy; + +public class RunTopMessageContext { + + public static String getMessage(RunTopMessageStrategy strategy) { + return strategy.createMessage(); + } +} diff --git a/src/main/java/com/run_us/server/domains/running/run/service/strategy/RunTopMessageStrategy.java b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RunTopMessageStrategy.java new file mode 100644 index 00000000..76b84f13 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/service/strategy/RunTopMessageStrategy.java @@ -0,0 +1,5 @@ +package com.run_us.server.domains.running.run.service.strategy; + +public interface RunTopMessageStrategy { + String createMessage(); +} diff --git a/src/main/java/com/run_us/server/domains/running/run/service/strategy/TimePlaceMessage.java b/src/main/java/com/run_us/server/domains/running/run/service/strategy/TimePlaceMessage.java new file mode 100644 index 00000000..02d85331 --- /dev/null +++ b/src/main/java/com/run_us/server/domains/running/run/service/strategy/TimePlaceMessage.java @@ -0,0 +1,18 @@ +package com.run_us.server.domains.running.run.service.strategy; + +import com.run_us.server.domains.running.run.domain.Run; + +import java.time.format.DateTimeFormatter; + +public class TimePlaceMessage implements RunTopMessageStrategy { + private final Run run; + + public TimePlaceMessage(Run run) { + this.run = run; + } + + @Override + public String createMessage() { + return run.getPreview().getBeginTime().format(DateTimeFormatter.ofPattern("M월 dd일 E요일 a h:mm")); + } +} diff --git a/src/main/java/com/run_us/server/domains/user/exception/UserErrorCode.java b/src/main/java/com/run_us/server/domains/user/exception/UserErrorCode.java index d6d30bf8..c69c2d1d 100644 --- a/src/main/java/com/run_us/server/domains/user/exception/UserErrorCode.java +++ b/src/main/java/com/run_us/server/domains/user/exception/UserErrorCode.java @@ -17,7 +17,10 @@ public enum UserErrorCode implements CustomResponseCode { REFRESH_FAILED("UEH4015", HttpStatus.UNAUTHORIZED, "리프레시 토큰이 만료되었습니다.", "리프레시 토큰이 만료되었습니다."), // 404 - USER_NOT_FOUND("UEH4041", HttpStatus.NOT_FOUND, "사용자를 찾을 수 없음", "사용자를 찾을 수 없음"),; + USER_NOT_FOUND("UEH4041", HttpStatus.NOT_FOUND, "사용자를 찾을 수 없음", "사용자를 찾을 수 없음"), + + // 409 + GET_USER_PROFILE_FAILED("UEH4091", HttpStatus.CONFLICT, "사용자의 프로필 정보를 가져올 수 없음", "사용자의 프로필 정보를 가져올 수 없음"); private final String code; private final HttpStatus httpStatusCode; diff --git a/src/main/java/com/run_us/server/domains/user/service/UserService.java b/src/main/java/com/run_us/server/domains/user/service/UserService.java index 0a3b070f..45ced0f9 100644 --- a/src/main/java/com/run_us/server/domains/user/service/UserService.java +++ b/src/main/java/com/run_us/server/domains/user/service/UserService.java @@ -34,6 +34,12 @@ public User getUserByPublicId(String publicId) { .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); } + public User getUserByInternalId(int internalId) { + return userRepository + .findByInternalId(internalId) + .orElseThrow(() -> UserException.of(USER_NOT_FOUND)); + } + public Map getUserMapByIds(List userIds) { if (userIds == null || userIds.isEmpty()) { return Collections.emptyMap(); diff --git a/src/main/java/com/run_us/server/global/common/GlobalConst.java b/src/main/java/com/run_us/server/global/common/GlobalConst.java index 9ed44e44..a743a43d 100644 --- a/src/main/java/com/run_us/server/global/common/GlobalConst.java +++ b/src/main/java/com/run_us/server/global/common/GlobalConst.java @@ -12,6 +12,8 @@ public final class GlobalConst { public static final String TIME_ZONE_ID = "Asia/Seoul"; public static final ZoneId ZONE_ID = ZoneId.of(TIME_ZONE_ID); + public static final String TIME_FORMAT_PATTERN = "yyyy/MM/dd HH:mm:ss"; + public static final String DEFAULT_IMG_URL = "default_img_url"; public static final String WS_USER_AUTH_HEADER = "user-id";