Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 36 additions & 9 deletions src/main/java/flipnote/group/adapter/in/web/JoinController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -11,22 +12,28 @@
import org.springframework.web.bind.annotation.RestController;

import flipnote.group.api.dto.request.ApplicationFormRequestDto;
import flipnote.group.api.dto.request.JoinRespondRequestDto;
import flipnote.group.api.dto.response.ApplicationFormResponseDto;
import flipnote.group.api.dto.response.FindJoinFormListResponseDto;
import flipnote.group.api.dto.response.JoinRespondResponseDto;
import flipnote.group.application.port.in.JoinRespondUseCase;
import flipnote.group.application.port.in.JoinUseCase;
import flipnote.group.application.port.in.command.ApplicationFormCommand;
import flipnote.group.application.port.in.command.FindJoinFormCommand;
import flipnote.group.application.port.in.command.JoinRespondCommand;
import flipnote.group.application.port.in.result.ApplicationFormResult;
import flipnote.group.application.port.in.result.FindJoinFormListResult;
import flipnote.group.application.port.in.result.JoinRespondResult;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/v1/groups/{groupId}")
@RequestMapping("/v1/groups/{groupId}/joins")
@RequiredArgsConstructor
public class JoinController {

private final JoinUseCase joinUseCase;
private final JoinRespondUseCase joinRespondUseCase;

/**
* 가입 신청 요청
Expand All @@ -35,7 +42,7 @@ public class JoinController {
* @param req
* @return
*/
@PostMapping("/joins")
@PostMapping("")
public ResponseEntity<ApplicationFormResponseDto> joinRequest(
@RequestHeader("X-USER-ID") Long userId,
@PathVariable("groupId") Long groupId,
Expand All @@ -57,7 +64,7 @@ public ResponseEntity<ApplicationFormResponseDto> joinRequest(
* @param groupId
* @return
*/
@GetMapping("/joins")
@GetMapping("")
public ResponseEntity<FindJoinFormListResponseDto> findGroupJoinList(
@RequestHeader("X-USER-ID") Long userId,
@PathVariable("groupId") Long groupId) {
Expand All @@ -68,12 +75,32 @@ public ResponseEntity<FindJoinFormListResponseDto> findGroupJoinList(

FindJoinFormListResponseDto res = FindJoinFormListResponseDto.from(result);

return ResponseEntity.status(HttpStatus.CREATED).body(res);
return ResponseEntity.ok(res);
}

/**
* 가입 신청 수락 여부 응답
* @param userId
* @param groupId
* @param joinId
* @param req
* @return
*/
@PatchMapping("/{joinId}")
public ResponseEntity<JoinRespondResponseDto> respondToJoinRequest(
@RequestHeader("X-USER-ID") Long userId,
@PathVariable("groupId") Long groupId,
@PathVariable("joinId") Long joinId,
@Valid @RequestBody JoinRespondRequestDto req) {

JoinRespondCommand cmd = new JoinRespondCommand(groupId, userId, joinId, req.joinStatus());

JoinRespondResult result = joinRespondUseCase.joinRespond(cmd);

JoinRespondResponseDto res = JoinRespondResponseDto.of(result);

return ResponseEntity.ok(res);
}

//todo 가입신청 응답

//todo 가입신청 삭제


//todo 내가 신청한 가입신청 리스트 조회
}
18 changes: 18 additions & 0 deletions src/main/java/flipnote/group/adapter/out/entity/GroupEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,22 @@ private static void validate(CreateGroupCommand cmd) {
throw new IllegalArgumentException("name too long");
}
}

public void plusCount() {

if(this.memberCount+1 > this.maxMember) {
throw new IllegalArgumentException("max member");
}

this.memberCount++;
}

public void minusCount() {

if(this.memberCount-1 < 0) {
throw new IllegalArgumentException("not minus member");
}

this.memberCount--;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public class JoinEntity extends BaseEntity {
private String form;

@Builder
private JoinEntity(Long userId, Long groupId, JoinStatus status, String form) {
private JoinEntity(Long id, Long userId, Long groupId, JoinStatus status, String form) {
this.id = id;
this.userId = userId;
this.groupId = groupId;
this.status = status;
Expand All @@ -56,4 +57,8 @@ public static JoinEntity create(Long groupId, Long userId, String form, JoinStat
.status(status)
.build();
}

public void updateStatus(JoinStatus status) {
this.status = status;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@

import org.springframework.stereotype.Repository;

import flipnote.group.adapter.out.entity.GroupEntity;
import flipnote.group.adapter.out.entity.GroupMemberEntity;
import flipnote.group.application.port.out.GroupMemberRepositoryPort;
import flipnote.group.domain.model.member.GroupMemberRole;
import flipnote.group.domain.model.member.MemberInfo;
import flipnote.group.infrastructure.persistence.jpa.GroupMemberRepository;
import flipnote.group.infrastructure.persistence.jpa.GroupRepository;
import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor
public class GroupMemberRepositoryAdapter implements GroupMemberRepositoryPort {

private final GroupMemberRepository groupMemberRepository;
private final GroupRepository groupRepository;

/**
* 그룹 멤버 저장
Expand All @@ -25,6 +28,13 @@ public class GroupMemberRepositoryAdapter implements GroupMemberRepositoryPort {
@Override
public void save(GroupMemberEntity groupMember) {
groupMemberRepository.save(groupMember);

GroupEntity groupEntity = groupRepository.findByIdForUpdate(groupMember.getGroupId()).orElseThrow(
() -> new IllegalArgumentException("not exist group")
);

//그룹 엔티티 + 1
groupEntity.plusCount();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import flipnote.group.application.port.out.GroupRepositoryPort;
import flipnote.group.domain.model.group.Category;
import flipnote.group.domain.model.group.GroupInfo;
import flipnote.group.infrastructure.persistence.querydsl.GroupRepository;
import flipnote.group.infrastructure.persistence.jpa.GroupRepository;
import lombok.RequiredArgsConstructor;

@Repository
Expand Down Expand Up @@ -57,4 +57,17 @@ public List<GroupInfo> findAllByCursorAndUserId(Long cursorId, Category category
public List<GroupInfo> findAllByCursorAndCreatedUserId(Long cursorId, Category category, int size, Long userId) {
return findAllByCursorAndCreatedUserId(cursorId, category, size, userId);
}

@Override
public boolean checkJoinable(Long groupId) {

GroupEntity groupEntity = groupRepository.findByIdForUpdate(groupId).orElseThrow(
() -> new IllegalArgumentException("not exists")
);

int maxMember = groupEntity.getMaxMember();
int count = groupEntity.getMemberCount();

return maxMember > count;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@ public List<JoinEntity> findFormList(Long groupId) {

return joinList;
}

@Override
public JoinEntity findJoin(Long joinId) {

JoinEntity entity = joinRepository.findById(joinId).orElseThrow(
() -> new IllegalArgumentException("not exist")
);
return entity;
}

@Override
public JoinEntity updateJoin(JoinEntity join) {
return joinRepository.save(join);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package flipnote.group.api.dto.request;

import flipnote.group.domain.model.join.JoinStatus;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;

public record JoinRespondRequestDto(
@NotNull(message = "그룹 신청 상태를 선택해주세요.")
@Pattern(regexp = "ACCEPT|REJECT", message = "ACCEPT 또는 REJECT만 입력 가능합니다.")
String status
) {
public JoinStatus joinStatus() {
return JoinStatus.valueOf(status);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package flipnote.group.api.dto.response;

import flipnote.group.application.port.in.result.JoinRespondResult;
import flipnote.group.domain.model.join.JoinStatus;

public record JoinRespondResponseDto(
Long joinId,
JoinStatus status
) {
public static JoinRespondResponseDto of(JoinRespondResult result) {

Long joinId = result.join().getId();
JoinStatus status = result.join().getStatus();

return new JoinRespondResponseDto(joinId, status);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package flipnote.group.application.port.in;

import flipnote.group.application.port.in.command.JoinRespondCommand;
import flipnote.group.application.port.in.result.JoinRespondResult;

public interface JoinRespondUseCase {
JoinRespondResult joinRespond(JoinRespondCommand cmd);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package flipnote.group.application.port.in.command;

import flipnote.group.domain.model.join.JoinStatus;

public record JoinRespondCommand(
Long groupId,
Long userId,
Long joinId,
JoinStatus status
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package flipnote.group.application.port.in.result;

import flipnote.group.adapter.out.entity.JoinEntity;

public record JoinRespondResult(
JoinEntity join
) {
public static JoinRespondResult of(JoinEntity join) {
return new JoinRespondResult(join);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public interface GroupRepositoryPort {
List<GroupInfo> findAllByCursorAndUserId(Long cursorId, Category category, int size, Long userId);

List<GroupInfo> findAllByCursorAndCreatedUserId(Long cursorId, Category category, int size, Long userId);

boolean checkJoinable(Long groupId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ public interface JoinRepositoryPort {
void save(JoinEntity join);

List<JoinEntity> findFormList(Long groupId);

JoinEntity findJoin(Long joinId);

JoinEntity updateJoin(JoinEntity join);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import flipnote.group.application.port.in.command.ChangeGroupCommand;
import flipnote.group.application.port.in.result.ChangeGroupResult;
import flipnote.group.domain.model.member.GroupMemberRole;
import flipnote.group.infrastructure.persistence.querydsl.GroupRepository;
import flipnote.group.infrastructure.persistence.jpa.GroupRepository;
import flipnote.image.grpc.v1.GetUrlByReferenceRequest;
import flipnote.image.grpc.v1.GetUrlByReferenceResponse;
import flipnote.image.grpc.v1.ImageCommandServiceGrpc;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package flipnote.group.application.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import flipnote.group.adapter.out.entity.GroupMemberEntity;
import flipnote.group.adapter.out.entity.JoinEntity;
import flipnote.group.adapter.out.entity.RoleEntity;
import flipnote.group.application.port.in.JoinRespondUseCase;
import flipnote.group.application.port.in.command.JoinRespondCommand;
import flipnote.group.application.port.in.result.JoinRespondResult;
import flipnote.group.application.port.out.GroupMemberRepositoryPort;
import flipnote.group.application.port.out.GroupRepositoryPort;
import flipnote.group.application.port.out.GroupRoleRepositoryPort;
import flipnote.group.application.port.out.JoinRepositoryPort;
import flipnote.group.domain.model.join.JoinStatus;
import flipnote.group.domain.model.member.GroupMemberRole;
import flipnote.group.domain.model.permission.GroupPermission;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class JoinRespondService implements JoinRespondUseCase {

private final JoinRepositoryPort joinRepository;
private final GroupRoleRepositoryPort groupRoleRepository;
private final GroupRepositoryPort groupRepository;
private final GroupMemberRepositoryPort groupMemberRepository;

private static final GroupPermission MANAGE = GroupPermission.JOIN_REQUEST_MANAGE;

/**
* 가입 신청 응답
* @param cmd
* @return
*/
@Override
@Transactional
public JoinRespondResult joinRespond(JoinRespondCommand cmd) {

//권한 체크
boolean existPermission = groupRoleRepository.checkPermission(cmd.userId(), cmd.groupId(), MANAGE);

if(!existPermission) {
throw new IllegalArgumentException("not permission");
}

JoinEntity join = joinRepository.findJoin(cmd.joinId());

if(join.getStatus().equals(JoinStatus.ACCEPT)) {
throw new IllegalArgumentException("already accept");
}

join.updateStatus(cmd.status());

//거절일 경우
if(cmd.status().equals(JoinStatus.REJECT)) {
JoinEntity response = joinRepository.updateJoin(join);

return new JoinRespondResult(response);
}

//수락일 경우
boolean joinable = groupRepository.checkJoinable(cmd.groupId());

//꽉찼을 경우
if(!joinable) {
throw new IllegalArgumentException("max member");
}

//가입 가능한 경우
RoleEntity role = groupRoleRepository.findByIdAndRole(cmd.groupId(), GroupMemberRole.MEMBER);

//주의: cmd의 유저가 아닌 join의 아이디로 해야함
GroupMemberEntity groupMember = GroupMemberEntity.create(cmd.groupId(), join.getUserId(), role);

groupMemberRepository.save(groupMember);

JoinEntity response = joinRepository.updateJoin(join);

return new JoinRespondResult(response);
}
}
Loading