Skip to content

Commit

Permalink
refactor: 어드민 유저 리팩토링 (#1068)
Browse files Browse the repository at this point in the history
* refactor: Owner 분리

* refactor: Student 패키지 분리

* refactor: User에 있는 정보 owner와 student로 리팩토링

* refactor: response 변수명 통일

* refactor: AdminOwnerService 리팩토링

* refactor: AdminOwnerService 리팩토링

* refactor: AdminOwnerService 리팩토링

* refactor: AdminStudentApi operation 수정

* refactor: 테스트 리팩토링

* refactor: User Validation 검증 패키지 추가

* refactor: 불필요한 import 제거

---------

Co-authored-by: 김원경 <[email protected]>
  • Loading branch information
kwoo28 and 김원경 authored Nov 25, 2024
1 parent 9e81d6d commit 109de38
Show file tree
Hide file tree
Showing 16 changed files with 1,217 additions and 965 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package in.koreatech.koin.admin.owner.controller;

import static in.koreatech.koin.domain.user.model.UserType.ADMIN;

import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;

import in.koreatech.koin.admin.user.dto.AdminNewOwnersResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnerResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnerUpdateRequest;
import in.koreatech.koin.admin.user.dto.AdminOwnerUpdateResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnersResponse;
import in.koreatech.koin.admin.user.dto.OwnersCondition;
import in.koreatech.koin.global.auth.Auth;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;

@Tag(name = "(Admin) Owner: 사장님", description = "관리자 권한으로 사장님 정보를 관리한다")
public interface AdminOwnerApi {

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
@ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))),
}
)
@Operation(summary = "사장님 권한 요청 허용")
@SecurityRequirement(name = "Jwt Authentication")
@PutMapping("/admin/owner/{id}/authed")
ResponseEntity<Void> allowOwnerPermission(
@PathVariable Integer id,
@Auth(permit = {ADMIN}) Integer adminId
);

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
@ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))),
}
)
@Operation(summary = "특정 사장님 조회")
@SecurityRequirement(name = "Jwt Authentication")
@GetMapping("/admin/users/owner/{id}")
ResponseEntity<AdminOwnerResponse> getOwner(
@PathVariable Integer id,
@Auth(permit = {ADMIN}) Integer adminId
);

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
@ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true))),
}
)
@Operation(summary = "특정 사장님 수정")
@SecurityRequirement(name = "Jwt Authentication")
@PutMapping("/admin/users/owner/{id}")
ResponseEntity<AdminOwnerUpdateResponse> updateOwner(
@PathVariable Integer id,
@RequestBody @Valid AdminOwnerUpdateRequest request,
@Auth(permit = {ADMIN}) Integer adminId
);

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
@ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true)))
}
)
@Operation(summary = "가입 신청한 사장님 리스트 조회 (페이지네이션)")
@SecurityRequirement(name = "Jwt Authentication")
@GetMapping("/admin/users/new-owners")
ResponseEntity<AdminNewOwnersResponse> getNewOwners(
@ParameterObject @ModelAttribute OwnersCondition ownersCondition,
@Auth(permit = {ADMIN}) Integer adminId
);

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
@ApiResponse(responseCode = "401", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", content = @Content(schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", content = @Content(schema = @Schema(hidden = true)))
}
)
@Operation(summary = "사장 리스트 조회 (페이지네이션)")
@SecurityRequirement(name = "Jwt Authentication")
@GetMapping("/admin/users/owners")
ResponseEntity<AdminOwnersResponse> getOwners(
@ParameterObject @ModelAttribute OwnersCondition ownersCondition,
@Auth(permit = {ADMIN}) Integer adminId
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package in.koreatech.koin.admin.owner.controller;

import static in.koreatech.koin.domain.user.model.UserType.ADMIN;

import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import in.koreatech.koin.admin.owner.service.AdminOwnerService;
import in.koreatech.koin.admin.user.dto.AdminNewOwnersResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnerResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnerUpdateRequest;
import in.koreatech.koin.admin.user.dto.AdminOwnerUpdateResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnersResponse;
import in.koreatech.koin.admin.user.dto.OwnersCondition;
import in.koreatech.koin.global.auth.Auth;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class AdminOwnerController implements AdminOwnerApi{

private final AdminOwnerService adminOwnerService;

@PutMapping("/admin/owner/{id}/authed")
public ResponseEntity<Void> allowOwnerPermission(
@PathVariable Integer id,
@Auth(permit = {ADMIN}) Integer adminId) {
adminOwnerService.allowOwnerPermission(id);
return ResponseEntity.ok().build();
}

@GetMapping("/admin/users/owner/{id}")
public ResponseEntity<AdminOwnerResponse> getOwner(
@PathVariable Integer id,
@Auth(permit = {ADMIN}) Integer adminId
) {
AdminOwnerResponse response = adminOwnerService.getOwner(id);
return ResponseEntity.ok().body(response);
}

@PutMapping("/admin/users/owner/{id}")
public ResponseEntity<AdminOwnerUpdateResponse> updateOwner(
@PathVariable Integer id,
@RequestBody @Valid AdminOwnerUpdateRequest request,
@Auth(permit = {ADMIN}) Integer adminId
) {
AdminOwnerUpdateResponse response = adminOwnerService.updateOwner(id, request);
return ResponseEntity.ok().body(response);
}

@GetMapping("/admin/users/new-owners")
public ResponseEntity<AdminNewOwnersResponse> getNewOwners(
@ParameterObject @ModelAttribute OwnersCondition ownersCondition,
@Auth(permit = {ADMIN}) Integer adminId
) {
return ResponseEntity.ok().body(adminOwnerService.getNewOwners(ownersCondition));
}

@GetMapping("/admin/users/owners")
public ResponseEntity<AdminOwnersResponse> getOwners(
@ParameterObject @ModelAttribute OwnersCondition ownersCondition,
@Auth(permit = {ADMIN}) Integer adminId
) {
return ResponseEntity.ok().body(adminOwnerService.getOwners(ownersCondition));
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package in.koreatech.koin.admin.user.repository;
package in.koreatech.koin.admin.owner.repository;

import java.util.Optional;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package in.koreatech.koin.admin.user.repository;
package in.koreatech.koin.admin.owner.repository;

import java.util.Optional;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package in.koreatech.koin.admin.owner.service;

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

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import in.koreatech.koin.admin.owner.repository.AdminOwnerRepository;
import in.koreatech.koin.admin.owner.repository.AdminOwnerShopRedisRepository;
import in.koreatech.koin.admin.shop.repository.AdminShopRepository;
import in.koreatech.koin.admin.user.dto.AdminNewOwnersResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnerResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnerUpdateRequest;
import in.koreatech.koin.admin.user.dto.AdminOwnerUpdateResponse;
import in.koreatech.koin.admin.user.dto.AdminOwnersResponse;
import in.koreatech.koin.admin.user.dto.OwnersCondition;
import in.koreatech.koin.admin.user.repository.AdminUserRepository;
import in.koreatech.koin.domain.owner.model.Owner;
import in.koreatech.koin.domain.owner.model.OwnerIncludingShop;
import in.koreatech.koin.domain.owner.model.OwnerShop;
import in.koreatech.koin.domain.shop.model.shop.Shop;
import in.koreatech.koin.domain.user.model.UserType;
import in.koreatech.koin.global.model.Criteria;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AdminOwnerService {

private final AdminOwnerRepository adminOwnerRepository;
private final AdminOwnerShopRedisRepository adminOwnerShopRedisRepository;
private final AdminShopRepository adminShopRepository;
private final AdminUserRepository adminUserRepository;

@Transactional
public void allowOwnerPermission(Integer id) {
Owner owner = adminOwnerRepository.getById(id);
owner.getUser().auth();
adminOwnerShopRedisRepository.findById(id).ifPresent(ownerShop -> {
Integer shopId = ownerShop.getShopId();
if (shopId != null) {
Shop shop = adminShopRepository.getById(shopId);
shop.updateOwner(owner);
owner.setGrantShop(true);
}
adminOwnerShopRedisRepository.deleteById(id);
});
}

public AdminOwnerResponse getOwner(Integer ownerId) {
Owner owner = adminOwnerRepository.getById(ownerId);

List<Integer> shopsId = adminShopRepository.findAllByOwnerId(ownerId)
.stream()
.map(Shop::getId)
.toList();

return AdminOwnerResponse.of(owner, shopsId);
}

@Transactional
public AdminOwnerUpdateResponse updateOwner(Integer ownerId, AdminOwnerUpdateRequest request) {
Owner owner = adminOwnerRepository.getById(ownerId);
owner.update(request);
return AdminOwnerUpdateResponse.from(owner);
}

public AdminNewOwnersResponse getNewOwners(OwnersCondition ownersCondition) {
ownersCondition.checkDataConstraintViolation();

Integer totalOwners = adminUserRepository.findUsersCountByUserTypeAndIsAuthed(UserType.OWNER, false);
Criteria criteria = Criteria.of(ownersCondition.page(), ownersCondition.limit(), totalOwners);
Sort.Direction direction = ownersCondition.getDirection();

Page<Owner> result = getNewOwnersResultPage(ownersCondition, criteria, direction);

List<OwnerIncludingShop> ownerIncludingShops = new ArrayList<>();
for (Owner owner: result.getContent()) {
adminOwnerShopRedisRepository.findById(owner.getId()).ifPresent(ownerShop -> {
Shop shop = adminShopRepository.findById(ownerShop.getShopId()).orElse(null);
OwnerIncludingShop ownerIncludingShop = OwnerIncludingShop.of(owner, shop);
ownerIncludingShops.add(ownerIncludingShop);
});
}

return AdminNewOwnersResponse.of(ownerIncludingShops, result, criteria);
}

public AdminOwnersResponse getOwners(OwnersCondition ownersCondition) {
ownersCondition.checkDataConstraintViolation();

Integer totalOwners = adminUserRepository.findUsersCountByUserTypeAndIsAuthed(UserType.OWNER, true);
Criteria criteria = Criteria.of(ownersCondition.page(), ownersCondition.limit(), totalOwners);
Sort.Direction direction = ownersCondition.getDirection();

Page<Owner> result = getOwnersResultPage(ownersCondition, criteria, direction);

return AdminOwnersResponse.of(result, criteria);
}

private Page<Owner> getNewOwnersResultPage(OwnersCondition ownersCondition, Criteria criteria,
Sort.Direction direction) {
PageRequest pageRequest = PageRequest.of(
criteria.getPage(),
criteria.getLimit(),
Sort.by(direction, "user.createdAt")
);

if (ownersCondition.searchType() == OwnersCondition.SearchType.EMAIL) {
return adminOwnerRepository.findPageUnauthenticatedOwnersByEmail(ownersCondition.query(), pageRequest);
}
if (ownersCondition.searchType() == OwnersCondition.SearchType.NAME) {
return adminOwnerRepository.findPageUnauthenticatedOwnersByName(ownersCondition.query(), pageRequest);
}
return adminOwnerRepository.findPageUnauthenticatedOwners(pageRequest);
}

private Page<Owner> getOwnersResultPage(OwnersCondition ownersCondition, Criteria criteria,
Sort.Direction direction) {
PageRequest pageRequest = PageRequest.of(
criteria.getPage(),
criteria.getLimit(),
Sort.by(direction, "user.createdAt")
);

if (ownersCondition.searchType() == OwnersCondition.SearchType.EMAIL) {
return adminOwnerRepository.findPageOwnersByEmail(ownersCondition.query(), pageRequest);
}
if (ownersCondition.searchType() == OwnersCondition.SearchType.NAME) {
return adminOwnerRepository.findPageOwnersByName(ownersCondition.query(), pageRequest);
}
return adminOwnerRepository.findPageOwners(pageRequest);
}
}
Loading

0 comments on commit 109de38

Please sign in to comment.