Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
5907785
CLAP-213 Feat: 작업보드 업데이트 usecase 세분화
joowojr Feb 2, 2025
d3bac55
CLAP-213 Feat: 비즈니스 정책을 명시하는 Policy 애너테이션 추가
joowojr Feb 2, 2025
dd55e7a
CLAP-213 Feat: Task 도메인 클래스에서 비즈니스 정책을 캡슐화하여 policy 클래스로 분리
joowojr Feb 2, 2025
6b3903d
CLAP-213 Feat: 비즈니스 정책을 담은 policy 클래스를 주입받아 리팩토링
joowojr Feb 2, 2025
3efd4f9
CLAP-213 Rename: 디렉토리 이동
joowojr Feb 2, 2025
a757b53
CLAP-213 Rename: 클래스명 수정
joowojr Feb 2, 2025
955854d
CLAP-213 Refactor: 작업의 상태가 REQUESTED일 때만 수정할 수 있도록 검증하는 정책 추가
joowojr Feb 2, 2025
c6097d0
CLAP-213 Rename: domain/policy 하위로 이동
joowojr Feb 2, 2025
0a319e3
CLAP-213 Refactor: 중복되는 알림 전송 관련 로직을 PublishNotificationService로 캡슐화
joowojr Feb 2, 2025
1d3673f
CLAP-213 Docs: todo 작성
joowojr Feb 2, 2025
2849397
conflict solve
Jan 25, 2025
178c6a5
merge conflict solve
Jan 28, 2025
167691a
merge conflict solve
Jan 28, 2025
f1d3075
CLAP-118 fix:'삭제'상태의 회원은 조회에서 제외
Jan 28, 2025
c62b532
CLAP-118 fix:Controller,dto Rename
Jan 29, 2025
2f5f00b
CLAP-118 fix:Controller 패키지 위치 변경 및 엔드포인트 수정
Jan 29, 2025
12e32fc
merge conflict solve
Jan 31, 2025
13d42cb
CLAP-156 Feat: member table 마이그레이션 파일 작성
joowojr Feb 2, 2025
3b2b897
CLAP-156 Feat: dev/ local 프로필에 대해 flyway 적용
joowojr Feb 2, 2025
940d002
CLAP-156 Feat: 파스칼 케이스로 수정
joowojr Feb 2, 2025
4a7dda0
CLAP-156 Feat: test환경 flyway 설정
joowojr Feb 2, 2025
dd626d3
CLAP-156 Feat: test 컨테이너에 flyway 비활성화 설정
joowojr Feb 2, 2025
27fff2e
CLAP-156 Feat: test 컨테이너에 flyway 비활성화 설정
joowojr Feb 2, 2025
ad5b618
CLAP-156 Feat: dev 환경 ddl-auto validate로 변경
joowojr Feb 2, 2025
2b4755d
merge conflict solve
starboxxxx Feb 1, 2025
64a3f5b
merge conflict solve
starboxxxx Feb 1, 2025
15bd3ca
CLAP-201 Fix: html 파일 변수 변경
starboxxxx Feb 1, 2025
6a45f79
CLAP-219 Fix: label color에 인디고 색상 추가
starboxxxx Feb 2, 2025
c3d1106
CLAP-214 Cleanup : 통계, 카테고리 미흡한부분 리팩토링
hyoseong-Choi Feb 2, 2025
ab88d7b
CLAP-214 Hotfix : WebMvcConfigurer addConverter 수정
hyoseong-Choi Feb 2, 2025
26ec2e2
CLAP-214 Hotfix : 엘라스틱서치 오류 수정중 추가한 파일들 불필요해져서 제거
hyoseong-Choi Feb 2, 2025
2ac8c81
CLAP-214 Hotfix : FindStatisticsController 스위치문 수정
hyoseong-Choi Feb 2, 2025
962d598
CLAP-214 Hotfix : AddCategoryService 지연로딩 오류 수정
hyoseong-Choi Feb 2, 2025
8ae7929
CLAP-196 Add: ContentCachingFilter 적용하여 request 캐싱
parkjaehak Feb 1, 2025
2fa4b86
CLAP-196 Fix: 작업 요청 목록 응답 imageUrl 추가
parkjaehak Feb 1, 2025
ea2e6b8
CLAP-196 Fix: 불필요한 주석 및 로그 제거
parkjaehak Feb 1, 2025
f803696
CLAP-196 Add: 에러 로깅을 위한 인터셉터 추가
parkjaehak Feb 2, 2025
212b13b
CLAP-196 Refactor: 예외를 통한 statusCode 파싱
parkjaehak Feb 2, 2025
ab15e70
CLAP-196 Fix: memberLogResponse requestAt으로 수정
parkjaehak Feb 2, 2025
49593a3
CLAP-196 Fix: 요청 실패 시 설명 구체화
parkjaehak Feb 2, 2025
f39063d
CLAP-196 Add: 제약 조건 수정을 위한 스크립트 추가
parkjaehak Feb 2, 2025
fb11142
CLAP-196 Fix: flyway 스크립트 병합
parkjaehak Feb 2, 2025
8b85fe6
CLAP-213 Refactor: merge conflict solve
joowojr Feb 2, 2025
1866866
CLAP-213 Refactor: 단일 첨부파일 업로드 방식으로 변경
joowojr Feb 2, 2025
66aa9f1
CLAP-213 Remove: 필요 없는 애너테이션 삭제
joowojr Feb 2, 2025
f7f6312
CLAP-213 Refactor: 작업 보드 조회 get 메서드로 수정
joowojr Feb 2, 2025
b79a82d
CLAP-213 Refactor: 작업 관련 상수들을 캡슐화한 클래스로 통합
joowojr Feb 2, 2025
fc5ed20
merge conflict solve
joowojr Feb 2, 2025
d61db8f
CLAP-213 Refactor: 작업 관련된 상수들을 캡슐화한 policy 클래스로 통합
joowojr Feb 2, 2025
8a47eff
CLAP-213 Refactor: query dsl custom repository로 분리
joowojr Feb 2, 2025
6e79776
Merge branch 'develop' into CLAP-213
joowojr Feb 2, 2025
d7cdcee
CLAP-213 Refactor: 중복되는 클래스 삭제
joowojr Feb 2, 2025
9b4ad67
Merge branch 'develop' into CLAP-213
joowojr Feb 3, 2025
4bd74cc
merge conflict solve
joowojr Feb 3, 2025
2074b5a
merge conflict fix
joowojr Feb 3, 2025
a40647e
Merge branch 'develop' into CLAP-213
joowojr Feb 3, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import clap.server.adapter.inbound.web.dto.admin.FindMemberRequest;
import clap.server.adapter.inbound.web.dto.admin.RetrieveAllMemberResponse;
import clap.server.application.mapper.RetrieveAllMemberMapper;
import clap.server.application.port.inbound.management.FindAllMembersUsecase;
import clap.server.application.port.inbound.management.FindMembersWithFilterUsecase;
import clap.server.application.port.inbound.admin.FindAllMembersUsecase;
import clap.server.application.port.inbound.admin.FindMembersWithFilterUsecase;
import clap.server.domain.model.member.Member;
import clap.server.exception.ApplicationException;
import clap.server.exception.code.MemberErrorCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import clap.server.application.port.inbound.task.FilterTaskBoardUsecase;
import clap.server.application.port.inbound.task.UpdateTaskBoardUsecase;
import clap.server.application.port.inbound.task.GetTaskBoardUsecase;
import clap.server.application.port.inbound.task.UpdateTaskOrderAndStatusUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand Down Expand Up @@ -35,15 +36,16 @@ public class TaskBoardController {
private final GetTaskBoardUsecase getTaskBoardUsecase;
private final FilterTaskBoardUsecase filterTaskBoardUsecase;
private final UpdateTaskBoardUsecase updateTaskBoardUsecase;
private final UpdateTaskOrderAndStatusUsecase updateTaskOrderAndStatus;

@Operation(summary = "작업 보드 조회 API")
@Secured({"ROLE_MANAGER"})
@PostMapping
@GetMapping
public ResponseEntity<TaskBoardResponse> getTaskBoard(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int pageSize,
@Parameter(description = "완료 일자 조회 기준, yyyy-mm-dd 형식으로 입력합니다.") @RequestParam(required = false)
@Parameter(description = "작업 완료 일자 조회 기준, yyyy-mm-dd 형식으로 입력합니다.") @RequestParam(required = false)
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate untilDate,
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "필터링 조회 request") @RequestBody(required = false) FilterTaskBoardRequest request,
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "필터링 조회 request") @ModelAttribute FilterTaskBoardRequest request,
@AuthenticationPrincipal SecurityUserDetails userInfo) {
Pageable pageable = PageRequest.of(page, pageSize);
if (request != null) {
Expand All @@ -62,7 +64,7 @@ public void updateTaskBoard(@Parameter(description = "전환될 작업의 상태
if (status == null) {
updateTaskBoardUsecase.updateTaskOrder(userInfo.getUserId(), request);
} else {
updateTaskBoardUsecase.updateTaskOrderAndStatus(userInfo.getUserId(), request, status);
updateTaskOrderAndStatus.updateTaskOrderAndStatus(userInfo.getUserId(), request, status);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,20 @@
import clap.server.application.port.outbound.member.CommandMemberPort;
import clap.server.application.port.outbound.member.LoadMemberPort;
import clap.server.common.annotation.architecture.PersistenceAdapter;
import clap.server.domain.model.task.Task;
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus ;
import clap.server.adapter.outbound.persistense.entity.task.TaskEntity;
import clap.server.adapter.outbound.persistense.repository.task.TaskRepository;
import clap.server.adapter.outbound.persistense.mapper.TaskPersistenceMapper;

import java.util.stream.Collectors;
import java.util.List;

import clap.server.domain.model.member.Member;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static clap.server.adapter.outbound.persistense.entity.member.QMemberEntity.memberEntity;

@PersistenceAdapter
@RequiredArgsConstructor
public class MemberPersistenceAdapter implements LoadMemberPort, CommandMemberPort {
public class MemberPersistenceAdapter implements LoadMemberPort, CommandMemberPort {
private final MemberRepository memberRepository;
private final MemberPersistenceMapper memberPersistenceMapper;
private final TaskRepository taskRepository;
private final TaskPersistenceMapper taskPersistenceMapper;
private final JPAQueryFactory jpaQueryFactory;


@Override
public Optional<Member> findById(final Long id) {
Expand Down Expand Up @@ -82,61 +64,13 @@ public void save(final Member member) {

@Override
public Page<Member> findAllMembers(Pageable pageable) {
return executeQueryWithPageable(pageable, new BooleanBuilder().and(memberEntity.status.ne(MemberStatus.DELETED)));
return memberRepository.findAllMembers(pageable).map(memberPersistenceMapper::toDomain);
}

@Override
public Page<Member> findMembersWithFilter(Pageable pageable, FindMemberRequest filterRequest) {
BooleanBuilder whereClause = createMemberFilter(filterRequest);
return executeQueryWithPageable(pageable, whereClause);
}

// 공통 쿼리 처리
private Page<Member> executeQueryWithPageable(Pageable pageable, BooleanBuilder whereClause) {
List<MemberEntity> entities = jpaQueryFactory
.selectFrom(memberEntity)
.where(whereClause)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

long total = jpaQueryFactory
.select(memberEntity.count())
.from(memberEntity)
.where(whereClause)
.fetchOne();

return new PageImpl<>(
entities.stream()
.map(memberPersistenceMapper::toDomain)
.toList(),
pageable,
total
);
}

// 필터 조건 생성
private BooleanBuilder createMemberFilter(FindMemberRequest filterRequest) {
BooleanBuilder whereClause = new BooleanBuilder();
whereClause.and(memberEntity.status.ne(MemberStatus.DELETED));

if (filterRequest.name() != null) {
whereClause.and(memberEntity.name.containsIgnoreCase(filterRequest.name()));
}
if (filterRequest.email() != null) {
whereClause.and(memberEntity.email.containsIgnoreCase(filterRequest.email()));
}
if (filterRequest.nickName() != null) {
whereClause.and(memberEntity.nickname.containsIgnoreCase(filterRequest.nickName()));
}
if (filterRequest.departmentName() != null) {
whereClause.and(memberEntity.department.name.containsIgnoreCase(filterRequest.departmentName()));
}
if (filterRequest.role() != null) {
whereClause.and(memberEntity.role.eq(filterRequest.role()));
}
return memberRepository.findMembersWithFilter(pageable, filterRequest).map(memberPersistenceMapper::toDomain);

return whereClause;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package clap.server.adapter.outbound.persistense.entity.task.constant;

import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.List;

@Getter
@RequiredArgsConstructor
public enum TaskStatus {
Expand All @@ -16,11 +13,4 @@ public enum TaskStatus {
TERMINATED("종료");

private final String description;

public static List<TaskStatus> getTaskBoardStatusList() {
return List.of(
TaskStatus.IN_PROGRESS,
TaskStatus.PENDING_COMPLETED,
TaskStatus.COMPLETED);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package clap.server.adapter.outbound.persistense.repository.member;

import clap.server.adapter.inbound.web.dto.admin.FindMemberRequest;
import clap.server.adapter.outbound.persistense.entity.member.MemberEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface MemberCustomRepository {
Page<MemberEntity> findAllMembers(Pageable pageable);
Page<MemberEntity> findMembersWithFilter(Pageable pageable, FindMemberRequest filterRequest) ;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package clap.server.adapter.outbound.persistense.repository.member;

import clap.server.adapter.inbound.web.dto.admin.FindMemberRequest;
import clap.server.adapter.outbound.persistense.entity.member.MemberEntity;
import clap.server.adapter.outbound.persistense.entity.member.constant.MemberStatus;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;

import java.util.List;

import static clap.server.adapter.outbound.persistense.entity.member.QMemberEntity.memberEntity;

@Repository
@RequiredArgsConstructor
public class MemberCustomRepositoryImpl implements MemberCustomRepository {
private final JPAQueryFactory queryFactory;

private Page<MemberEntity> executeQueryWithPageable(Pageable pageable, BooleanBuilder whereClause) {
List<MemberEntity> result = queryFactory
.selectFrom(memberEntity)
.where(whereClause)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

long total = queryFactory
.select(memberEntity.count())
.from(memberEntity)
.where(whereClause)
.fetch().size();

return new PageImpl<>(
result,
pageable,
total
);
}

// 필터 조건 생성
private BooleanBuilder createMemberFilter(FindMemberRequest filterRequest) {
BooleanBuilder whereClause = new BooleanBuilder();
whereClause.and(memberEntity.status.ne(MemberStatus.DELETED));

if (filterRequest.name() != null) {
whereClause.and(memberEntity.name.containsIgnoreCase(filterRequest.name()));
}
if (filterRequest.email() != null) {
whereClause.and(memberEntity.email.containsIgnoreCase(filterRequest.email()));
}
if (filterRequest.nickName() != null) {
whereClause.and(memberEntity.nickname.containsIgnoreCase(filterRequest.nickName()));
}
if (filterRequest.departmentName() != null) {
whereClause.and(memberEntity.department.name.eq(filterRequest.departmentName()));
}
if (filterRequest.role() != null) {
whereClause.and(memberEntity.role.eq(filterRequest.role()));
}

return whereClause;
}

@Override
public Page<MemberEntity> findAllMembers(Pageable pageable) {
return executeQueryWithPageable(pageable, new BooleanBuilder().and(memberEntity.status.ne(MemberStatus.DELETED)));
}

@Override
public Page<MemberEntity> findMembersWithFilter(Pageable pageable, FindMemberRequest filterRequest) {
BooleanBuilder whereClause = createMemberFilter(filterRequest);
return executeQueryWithPageable(pageable, whereClause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
import clap.server.adapter.outbound.persistense.entity.member.constant.MemberRole;
import clap.server.adapter.outbound.persistense.entity.member.constant.MemberStatus;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface MemberRepository extends JpaRepository<MemberEntity, Long>, JpaSpecificationExecutor<MemberEntity> {
public interface MemberRepository extends JpaRepository<MemberEntity, Long>, MemberCustomRepository {


List<MemberEntity> findByRoleAndStatus(MemberRole role, MemberStatus status);
Expand All @@ -23,6 +22,9 @@ public interface MemberRepository extends JpaRepository<MemberEntity, Long>, Jpa

List<MemberEntity> findByIsReviewerTrue();

List<MemberEntity> findAll(); // 전체 회원 조회


Optional<MemberEntity> findByMemberIdAndIsReviewerTrue(Long memberId);
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
import java.util.List;

import static clap.server.adapter.outbound.persistense.entity.task.QTaskEntity.taskEntity;
import static com.querydsl.core.types.Order.*;
import static com.querydsl.core.types.Order.ASC;
import static com.querydsl.core.types.Order.DESC;

@Repository
@RequiredArgsConstructor
Expand Down
12 changes: 0 additions & 12 deletions src/main/java/clap/server/application/mapper/AttachmentMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,6 @@ public static List<Attachment> toTaskAttachments(Task task, List<MultipartFile>
.toList();
}

public static List<Attachment> toCommentAttachments(Task task, Comment comment, List<MultipartFile> files, List<String> fileUrls) {
return IntStream.range(0, files.size())
.mapToObj(i -> createCommentAttachment(
task,
comment,
files.get(i).getOriginalFilename(),
fileUrls.get(i),
files.get(i).getSize()
))
.toList();
}


public static List<AttachmentResponse> toAttachmentResponseList(List<Attachment> attachments) {
return attachments.stream()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package clap.server.application.port.inbound.admin;

import clap.server.domain.model.member.Member;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface FindAllMembersUsecase {
Page<Member> findAllMembers(Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package clap.server.application.port.inbound.admin;

import clap.server.adapter.inbound.web.dto.admin.FindMemberRequest;
import clap.server.domain.model.member.Member;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface FindMembersWithFilterUsecase {
Page<Member> findMembersWithFilter(Pageable pageable, FindMemberRequest filterRequest);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package clap.server.application.port.inbound.domain;

import clap.server.application.port.outbound.member.CommandMemberPort;
import clap.server.application.port.outbound.member.LoadMemberPort;
import clap.server.domain.model.member.Member;
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus;
Expand All @@ -15,8 +14,6 @@
@RequiredArgsConstructor
public class MemberService {
private final LoadMemberPort loadMemberPort;
private final CommandMemberPort commandMemberPort;


public Member findById(Long memberId) {
return loadMemberPort.findById(memberId).orElseThrow(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package clap.server.application.port.inbound.task;

import clap.server.adapter.inbound.web.dto.task.request.UpdateTaskOrderRequest;
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus;

public interface UpdateTaskBoardUsecase {
void updateTaskOrder(Long processorId, UpdateTaskOrderRequest request);
void updateTaskOrderAndStatus(Long processorId, UpdateTaskOrderRequest request, TaskStatus status);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package clap.server.application.port.inbound.task;

import clap.server.adapter.inbound.web.dto.task.request.UpdateTaskOrderRequest;
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus;

public interface UpdateTaskOrderAndStatusUsecase {
void updateTaskOrderAndStatus(Long processorId, UpdateTaskOrderRequest request, TaskStatus status);
}
Loading