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
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
import greenfirst.be.global.common.security.CustomUserDetails;
import greenfirst.be.user.adapter.in.web.response.UserProfileResponse;
import greenfirst.be.user.adapter.in.web.response.UserSimpleDataListResponse;
import greenfirst.be.user.adapter.in.web.response.WithdrawUserListResponse;
import greenfirst.be.user.application.dto.in.GetUserByUuidInDto;
import greenfirst.be.user.application.dto.in.GetUserSimpleDataListInDto;
import greenfirst.be.user.application.dto.in.GetWithdrawUserListInDto;
import greenfirst.be.user.application.dto.out.UserDataListOutDto;
import greenfirst.be.user.application.dto.out.WithdrawUserListOutDto;
import greenfirst.be.user.application.service.GetUserDataService;
import greenfirst.be.user.domain.model.Users;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -44,6 +49,7 @@ public class GetUserDataController {
* 1. (admin/agency) 전체 유저 목록 조회
* 2. (common) 본인 프로필 조회
* 3. (admin/agency) 다른 유저 프로필 조회
* 4. (admin) 탈퇴 유저 목록 조회
*/

// 1. (admin/agency) 유저 목록 조회/검색
Expand Down Expand Up @@ -79,6 +85,56 @@ public BaseResponse<UserSimpleDataListResponse> getUserList(
}


// 4. (admin) 탈퇴 유저 목록 조회
@Operation(summary = "(관리자) 탈퇴 유저 목록 조회/검색", description = "탈퇴 유저 목록을 타입별로 조회하거나, 이름/휴대폰 번호로 검색 진행", tags = { "User - Admin" })
@GetMapping("/withdraw/list")
@PreAuthorize("hasAuthority('ADMIN')")
@SecurityRequirement(name = "Bearer Auth")
public BaseResponse<WithdrawUserListResponse> getWithdrawUserList(
@Parameter(description = "이름 부분 검색 (null/blank면 미적용)") @RequestParam(required = false) String userName,
@Parameter(description = "전화번호 부분 검색 (null/blank면 미적용)") @RequestParam(required = false) String userPhoneNumber,
@Parameter(description = "탈퇴 회원 타입 필터 (미입력 시 USER/PERSONAL_PARTNER/CORPORATE_PARTNER/AGENCY 기본 적용)")
@Schema(allowableValues = { "USER", "PERSONAL_PARTNER", "CORPORATE_PARTNER", "AGENCY" })
@RequestParam(required = false) List<UserType> userTypeList,
@Parameter(description = "탈퇴 시기 정렬 (기본 DESC)")
@Schema(allowableValues = { "ASC", "DESC" })
@RequestParam(required = false) String orderType,
@Nullable @PageableDefault Pageable pageable,
@AuthenticationPrincipal CustomUserDetails authentication
) {

// default user types
List<UserType> allowedUserTypes = List.of(UserType.USER, UserType.PERSONAL_PARTNER, UserType.CORPORATE_PARTNER, UserType.AGENCY);
List<UserType> resolvedUserTypes = (userTypeList == null || userTypeList.isEmpty())
? allowedUserTypes
: userTypeList.stream()
.filter(allowedUserTypes::contains)
.distinct()
.toList();

if (resolvedUserTypes.isEmpty()) {
resolvedUserTypes = allowedUserTypes;
}

// mapping
GetWithdrawUserListInDto inDto = GetWithdrawUserListInDto.builder()
.userName(userName)
.userPhoneNumber(userPhoneNumber)
.userTypeList(resolvedUserTypes)
.orderType(orderType)
.pageable(pageable)
.requestorUuid(authentication.getUserUuid())
.build();

// 탈퇴 유저 목록 조회
WithdrawUserListOutDto outDto = getUserDataService.getWithdrawUserList(inDto);

// result
WithdrawUserListResponse response = WithdrawUserListResponse.from(outDto);
return new BaseResponse<>(response);
}


// 2. (common) 본인 프로필 조회
@Operation(summary = "본인 프로필 조회", description = "로그인한 사용자 본인의 프로필 정보를 조회합니다", tags = { "User - Admin", "User - Agency", "User - Partner", "User - User" })
@GetMapping("/profile/my")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package greenfirst.be.user.adapter.in.web.response;


import greenfirst.be.global.common.response.pagination.CustomPaginationResponse;
import greenfirst.be.user.application.dto.out.WithdrawUserListOutDto;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

import java.util.List;


@Getter
@SuperBuilder(toBuilder = true)
Copy link

Copilot AI Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method overrides CustomPaginationResponse.toBuilder; it is advisable to add an Override annotation.

Copilot uses AI. Check for mistakes.
@NoArgsConstructor
@AllArgsConstructor
public class WithdrawUserListResponse extends CustomPaginationResponse {

private List<WithdrawUserResponse> content;

public static WithdrawUserListResponse from(WithdrawUserListOutDto outDto) {

List<WithdrawUserResponse> content = outDto.getContent().stream()
.map(WithdrawUserResponse::from)
.toList();

return WithdrawUserListResponse.builder()
.content(content)
.totalElementCount(outDto.getTotalElementCount())
.totalPageCount(outDto.getTotalPageCount())
.number(outDto.getNumber())
.size(outDto.getSize())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package greenfirst.be.user.adapter.in.web.response;


import greenfirst.be.user.application.dto.out.WithdrawUserSimpleDataOutDto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.UUID;


@Getter
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class WithdrawUserResponse {

private UUID userUuid;
private String userType;
private String userName;
private String userPhoneNumber;
private String userLoginId;
private LocalDateTime deletedAt;

public static WithdrawUserResponse from(WithdrawUserSimpleDataOutDto outDto) {
return WithdrawUserResponse.builder()
.userUuid(outDto.getUserUuid())
.userType(outDto.getUserType())
.userName(outDto.getUserName())
.userPhoneNumber(outDto.getUserPhoneNumber())
.userLoginId(outDto.getUserLoginId())
.deletedAt(outDto.getDeletedAt())
.build();
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
import greenfirst.be.user.application.dto.in.GetUserSimpleDataListInDto;
import greenfirst.be.user.application.dto.out.UserDataListOutDto;
import greenfirst.be.user.application.dto.out.UserSimpleDataOutDto;
import greenfirst.be.user.application.dto.in.GetWithdrawUserListInDto;
import greenfirst.be.user.application.dto.out.WithdrawUserListOutDto;
import greenfirst.be.user.application.dto.out.WithdrawUserSimpleDataOutDto;
import greenfirst.be.vehicle.adapter.out.persistence.entity.QVehicleEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -36,6 +39,7 @@ public class UserQuerydslRepository {
/**
* UserQuerydslRepository
* 1. 유저 목록 조회
* 2. 탈퇴 유저 목록 조회
*/

// 1. 유저 목록 조회
Expand Down Expand Up @@ -97,4 +101,57 @@ public UserDataListOutDto getUserSimpleDataList(GetUserSimpleDataListInDto inDto

}

// 2. 탈퇴 유저 목록 조회
public WithdrawUserListOutDto getWithdrawUserList(GetWithdrawUserListInDto inDto) {

// paging
Pageable pageable = inDto.getPageable();
long offset = pageable.getOffset();
int pageSize = pageable.getPageSize();

// conditions
BooleanBuilder where = new BooleanBuilder()
.and(userUtil.withdrawUserFilter(qUser))
.and(userUtil.userTypeFilter(qUser, inDto.getUserTypeList()))
.and(userUtil.userNameSearch(qUser, inDto.getUserName()))
.and(userUtil.userPhoneNumberSearch(qUser, inDto.getUserPhoneNumber()));

// content
List<WithdrawUserSimpleDataOutDto> content = queryFactory
.select(Projections.constructor(WithdrawUserSimpleDataOutDto.class,
qUser.userUuid,
qUser.userType,
qUser.userName,
qUser.userPhoneNumber,
qUser.userLoginId,
qUser.deletedAt
))
.from(qUser)
.where(where)
.offset(offset)
.limit(pageSize)
.orderBy(userUtil.withdrawUserOrder(qUser, inDto.getOrderType()))
.fetch();

// total element count
Long totalElementCount = queryFactory
.select(qUser.count())
.from(qUser)
.where(where)
.fetchFirst();

// total page count
long totalPageCount = commonUtil.calculateTotalPage(pageable, totalElementCount);

// return
return WithdrawUserListOutDto.builder()
.content(content)
.totalElementCount(totalElementCount)
.totalPageCount(totalPageCount)
.number(pageable.getPageNumber() + 1)
.size(pageable.getPageSize())
.build();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.OrderSpecifier;
import greenfirst.be.global.common.enums.common.UserType;
import greenfirst.be.user.adapter.out.persistence.entity.QUserEntity;
import greenfirst.be.vehicle.adapter.out.persistence.entity.QVehicleEntity;
Expand All @@ -14,6 +15,8 @@
@Component
public class UserQuerydslUtil {

private static final String DESC = "DESC";

// 유저 타입별 필터
public @Nullable BooleanExpression userTypeFilter(QUserEntity qUser, List<UserType> userTypeList) {

Expand Down Expand Up @@ -57,4 +60,19 @@ public class UserQuerydslUtil {
return qUser.deletedAt.isNull();
}

// 탈퇴 사용자 필터 (삭제된 사용자만)
public @Nullable BooleanExpression withdrawUserFilter(QUserEntity qUser) {
return qUser.deletedAt.isNotNull();
}

// 탈퇴일 정렬
public OrderSpecifier<?> withdrawUserOrder(QUserEntity qUser, String orderType) {

String normalizedOrderType = orderType == null || orderType.isBlank() || orderType.equalsIgnoreCase(DESC)
? DESC
: "ASC";

return normalizedOrderType.equals(DESC) ? qUser.deletedAt.desc() : qUser.deletedAt.asc();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import greenfirst.be.user.adapter.out.persistence.jpa.UserJpaRepository;
import greenfirst.be.user.adapter.out.persistence.querydsl.UserQuerydslRepository;
import greenfirst.be.user.application.dto.in.GetUserSimpleDataListInDto;
import greenfirst.be.user.application.dto.in.GetWithdrawUserListInDto;
import greenfirst.be.user.application.dto.out.UserDataListOutDto;
import greenfirst.be.user.application.dto.out.WithdrawUserListOutDto;
import greenfirst.be.user.application.port.out.repository.UserQueryRepository;
import greenfirst.be.user.domain.model.Users;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -59,6 +61,12 @@ public UserDataListOutDto getUserSimpleDataList(GetUserSimpleDataListInDto inDto
return userQuerydslRepository.getUserSimpleDataList(inDto);
}

// 조건에 맞는 탈퇴 유저 목록 조회
@Override
public WithdrawUserListOutDto getWithdrawUserList(GetWithdrawUserListInDto inDto) {
return userQuerydslRepository.getWithdrawUserList(inDto);
}


// 로그인 아이디로 유저 존재 확인
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package greenfirst.be.user.application.dto.in;


import greenfirst.be.global.common.enums.common.UserType;
import lombok.Builder;
import lombok.Getter;
import org.springframework.data.domain.Pageable;

import java.util.List;
import java.util.UUID;


@Getter
@Builder
public class GetWithdrawUserListInDto {

private String userName;
private String userPhoneNumber;
private List<UserType> userTypeList;
private String orderType;
private Pageable pageable;
private UUID requestorUuid;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package greenfirst.be.user.application.dto.out;


import greenfirst.be.global.common.response.pagination.CustomPaginationResponse;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

import java.util.List;


@Getter
@SuperBuilder
public class WithdrawUserListOutDto extends CustomPaginationResponse {

private List<WithdrawUserSimpleDataOutDto> content;

}
Loading