From 37c849f472894bce55bedee4cacaf0dcd4bb531a Mon Sep 17 00:00:00 2001 From: HMHMHMJUN Date: Thu, 10 Jul 2025 15:42:06 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat=20:=20=EC=97=85=EC=B2=B4=20=EB=82=B4?= =?UTF-8?q?=20=EC=82=AC=EC=9B=90=20=EC=9D=B4=EB=A6=84=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=B6=94=EA=B0=80=20#350?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/repository/MemberRepository.java | 12 ++++---- .../domain/member/service/MemberService.java | 29 +++++++++---------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/main/java/kr/mywork/domain/member/repository/MemberRepository.java b/src/main/java/kr/mywork/domain/member/repository/MemberRepository.java index 8252a878..76c7996f 100644 --- a/src/main/java/kr/mywork/domain/member/repository/MemberRepository.java +++ b/src/main/java/kr/mywork/domain/member/repository/MemberRepository.java @@ -1,19 +1,19 @@ package kr.mywork.domain.member.repository; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - import kr.mywork.domain.company.service.dto.response.MemberDetailResponse; import kr.mywork.domain.member.model.Member; import kr.mywork.domain.member.service.dto.response.MemberSelectResponse; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + public interface MemberRepository { Optional findByEmailAndDeletedFalse(String email); - List findMemberByCompanyId(UUID companyId, int page, int memberPageSize); + List findMemberByCompanyId(UUID companyId, int page, int memberPageSize, String memberName); - long countByCompanyIdAndDeletedFalse(UUID companyId); + long countByCompanyIdAndDeletedFalse(UUID companyId,String memberName); Member save(Member member); diff --git a/src/main/java/kr/mywork/domain/member/service/MemberService.java b/src/main/java/kr/mywork/domain/member/service/MemberService.java index 48063db7..99e2acb8 100644 --- a/src/main/java/kr/mywork/domain/member/service/MemberService.java +++ b/src/main/java/kr/mywork/domain/member/service/MemberService.java @@ -1,16 +1,5 @@ package kr.mywork.domain.member.service; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - import kr.mywork.common.auth.components.dto.LoginMemberDetail; import kr.mywork.domain.activityLog.listener.eventObject.ActivityLogCreateEvent; import kr.mywork.domain.activityLog.listener.eventObject.ActivityLogDeleteEvent; @@ -25,6 +14,16 @@ import kr.mywork.domain.member.service.dto.response.MemberSelectResponse; import kr.mywork.interfaces.member.controller.dto.request.ResetPasswordWebRequest; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -38,9 +37,9 @@ public class MemberService { private final ApplicationEventPublisher eventPublisher; @Transactional - public List findMemberByCompanyId(UUID companyId, int page) { + public List findMemberByCompanyId(UUID companyId, int page, String memberName) { - return memberRepository.findMemberByCompanyId(companyId, page, memberPageSize) + return memberRepository.findMemberByCompanyId(companyId, page, memberPageSize, memberName) .stream() .map(CompanyMemberResponse::fromEntity) .collect(Collectors.toList()); @@ -48,8 +47,8 @@ public List findMemberByCompanyId(UUID companyId, int pag } @Transactional - public long countMembersByCompanyId(UUID companyId) { - return memberRepository.countByCompanyIdAndDeletedFalse(companyId); + public long countMembersByCompanyId(UUID companyId, String memberName) { + return memberRepository.countByCompanyIdAndDeletedFalse(companyId,memberName); } @Transactional From ec6e5c201ed1fc40df1b888a00d4940a7c72704d Mon Sep 17 00:00:00 2001 From: HMHMHMJUN Date: Thu, 10 Jul 2025 15:46:48 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat=20:=20=EC=97=85=EC=B2=B4=20=EB=82=B4?= =?UTF-8?q?=20=EC=82=AC=EC=9B=90=20=EC=9D=B4=EB=A6=84=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20#350?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../company/controller/CompanyController.java | 40 ++++++------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/src/main/java/kr/mywork/interfaces/company/controller/CompanyController.java b/src/main/java/kr/mywork/interfaces/company/controller/CompanyController.java index 3da32255..e57f85f3 100644 --- a/src/main/java/kr/mywork/interfaces/company/controller/CompanyController.java +++ b/src/main/java/kr/mywork/interfaces/company/controller/CompanyController.java @@ -1,19 +1,5 @@ package kr.mywork.interfaces.company.controller; -import java.util.List; -import java.util.UUID; - -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Pattern; import kr.mywork.common.api.support.response.ApiResponse; @@ -29,18 +15,15 @@ import kr.mywork.domain.member.service.dto.response.CompanyMemberResponse; import kr.mywork.interfaces.company.controller.dto.request.CompanyCreateWebRequest; import kr.mywork.interfaces.company.controller.dto.request.CompanyUpdateWebRequest; -import kr.mywork.interfaces.company.controller.dto.response.CompanyCreateWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanyDeleteWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanyDetailWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanyIdCreateWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanyListWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanyNameWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanyNamesWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanySelectWebResponse; -import kr.mywork.interfaces.company.controller.dto.response.CompanyUpdateWebResponse; +import kr.mywork.interfaces.company.controller.dto.response.*; import kr.mywork.interfaces.member.controller.dto.response.CompanyMemberListWebResponse; import kr.mywork.interfaces.member.controller.dto.response.CompanyMemberWebResponse; import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; @RestController @RequiredArgsConstructor @@ -141,11 +124,14 @@ public ApiResponse companyListOnlyIdNameWebResponseApiR } @GetMapping("/{companyId}/members") - public ApiResponse getCompanyMember(@PathVariable(name = "companyId") UUID companyId, - @RequestParam(defaultValue = "1") @Min(value = 1, message = "{invalid.page-size}") int page) { - List companyMemberResponses = memberService.findMemberByCompanyId(companyId, page); + public ApiResponse getCompanyMember( + @PathVariable(name = "companyId") UUID companyId, + @RequestParam(defaultValue = "1") @Min(value = 1, message = "{invalid.page-size}") int page, + @RequestParam(name = "memberName", required = false) final String memberName + ) { + List companyMemberResponses = memberService.findMemberByCompanyId(companyId, page,memberName); - long total = memberService.countMembersByCompanyId(companyId); + long total = memberService.countMembersByCompanyId(companyId,memberName); List companyMemberWebResponses = companyMemberResponses.stream() .map(CompanyMemberListWebResponse::fromService) From 8b68c58a1069b3a92e605af04429b0c60aa3b561 Mon Sep 17 00:00:00 2001 From: HMHMHMJUN Date: Thu, 10 Jul 2025 15:47:13 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat=20:=20=EC=97=85=EC=B2=B4=20=EB=82=B4?= =?UTF-8?q?=20=EC=82=AC=EC=9B=90=20=EC=9D=B4=EB=A6=84=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=EC=BF=BC=EB=A6=AC=20#350?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/rdb/QueryDslMemberRepository.java | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/main/java/kr/mywork/infrastructure/member/rdb/QueryDslMemberRepository.java b/src/main/java/kr/mywork/infrastructure/member/rdb/QueryDslMemberRepository.java index cf0100c8..c33b0243 100644 --- a/src/main/java/kr/mywork/infrastructure/member/rdb/QueryDslMemberRepository.java +++ b/src/main/java/kr/mywork/infrastructure/member/rdb/QueryDslMemberRepository.java @@ -2,6 +2,7 @@ import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import kr.mywork.domain.company.service.dto.response.MemberDetailResponse; import kr.mywork.domain.member.model.Member; @@ -31,23 +32,41 @@ public Optional findByEmailAndDeletedFalse(String email) { } @Override - public List findMemberByCompanyId(UUID companyId, int page, int memberPageSize) { + public List findMemberByCompanyId(UUID companyId, int page, int memberPageSize,String memberName) { final int offset = (page - 1) * memberPageSize; return queryFactory - .selectFrom(member) - .where( - member.companyId.eq(companyId), - member.deleted.eq(false)) - .orderBy(member.name.asc()) - .offset(offset) - .limit(memberPageSize) - .fetch(); + .selectFrom(member) + .where( + member.companyId.eq(companyId), + member.deleted.eq(false), + memberNameCondition(memberName) + ) + .orderBy(member.name.asc()) + .offset(offset) + .limit(memberPageSize) + .fetch(); + } + + private BooleanExpression memberNameCondition(String memberName) { + if (memberName == null || memberName.trim().isEmpty()) { + return null; + } + return member.name.containsIgnoreCase(memberName); } @Override - public long countByCompanyIdAndDeletedFalse(UUID companyId) { - return memberRepository.countByCompanyIdAndDeletedFalse(companyId); + public long countByCompanyIdAndDeletedFalse(UUID companyId,String memberName) { + Long result = queryFactory + .select(member.count()) + .from(member) + .where( + member.companyId.eq(companyId), + member.deleted.eq(false), + memberNameCondition(memberName) // 부분 검색 조건 + ) + .fetchOne(); + return result != null ? result : 0L; } @Override From 544d60b69e22aa9794cee0d924e98752e60ee082 Mon Sep 17 00:00:00 2001 From: HMHMHMJUN Date: Thu, 10 Jul 2025 15:47:27 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat=20:=20=EC=97=85=EC=B2=B4=20=EB=82=B4?= =?UTF-8?q?=20=EC=82=AC=EC=9B=90=20=EC=9D=B4=EB=A6=84=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20#350?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mywork/docs/CompanyDocumentationTest.java | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/test/java/kr/mywork/docs/CompanyDocumentationTest.java b/src/test/java/kr/mywork/docs/CompanyDocumentationTest.java index a1f1377f..0cc65d26 100644 --- a/src/test/java/kr/mywork/docs/CompanyDocumentationTest.java +++ b/src/test/java/kr/mywork/docs/CompanyDocumentationTest.java @@ -1,19 +1,11 @@ package kr.mywork.docs; -import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document; -import static com.epages.restdocs.apispec.ResourceDocumentation.headerWithName; -import static com.epages.restdocs.apispec.ResourceDocumentation.parameterWithName; -import static com.epages.restdocs.apispec.ResourceDocumentation.resource; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.UUID; - +import com.epages.restdocs.apispec.ResourceSnippet; +import com.epages.restdocs.apispec.ResourceSnippetParameters; +import com.fasterxml.uuid.Generators; +import kr.mywork.common.api.support.response.ResultType; +import kr.mywork.interfaces.company.controller.dto.request.CompanyCreateWebRequest; +import kr.mywork.interfaces.company.controller.dto.request.CompanyUpdateWebRequest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; @@ -23,13 +15,14 @@ import org.springframework.test.context.jdbc.Sql; import org.springframework.test.web.servlet.ResultActions; -import com.epages.restdocs.apispec.ResourceSnippet; -import com.epages.restdocs.apispec.ResourceSnippetParameters; -import com.fasterxml.uuid.Generators; +import java.util.UUID; -import kr.mywork.common.api.support.response.ResultType; -import kr.mywork.interfaces.company.controller.dto.request.CompanyCreateWebRequest; -import kr.mywork.interfaces.company.controller.dto.request.CompanyUpdateWebRequest; +import static com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper.document; +import static com.epages.restdocs.apispec.ResourceDocumentation.*; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class CompanyDocumentationTest extends RestDocsDocumentation { @@ -464,6 +457,7 @@ private ResourceSnippet findAllCompanyListSuccessResource() { final ResultActions result = mockMvc.perform( get("/api/companies/{companyId}/members", id) .param("page", "1") + .param("memberName","김민수") .contentType(MediaType.APPLICATION_JSON) .header(HttpHeaders.AUTHORIZATION, toBearerAuthorizationHeader(accessToken))); @@ -483,7 +477,8 @@ private ResourceSnippet CompanyMemberGetSuccess() { .summary("회사의 직원 목록 조회 API") .description("회사의 직원 목록을 조회한다.") .queryParameters( - parameterWithName("page").description("페이지 번호")) + parameterWithName("page").description("페이지 번호"), + parameterWithName("memberName").optional().description("이름 검색어 (부분 일치 검색)")) .requestHeaders( headerWithName(HttpHeaders.CONTENT_TYPE).description("컨텐츠 타입"), headerWithName(HttpHeaders.AUTHORIZATION).description("엑세스 토큰"))