Skip to content

Commit

Permalink
feature: admin dashboard (#138)
Browse files Browse the repository at this point in the history
* feature: user statistics in admin dashboard

* feature: product order count in admin dashboard

* feature: clothing sales count in admin dashboard

* feature: today stats in admin dashboard

* fix: no quality rate for rejected products (admin)
  • Loading branch information
hyunihs authored Aug 16, 2024
1 parent 34926c4 commit 8339825
Show file tree
Hide file tree
Showing 17 changed files with 162 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,18 @@ public SuccessResponse<GetClothingSalesUser> getClothingSalesUserInfo(@PathVaria
return SuccessResponse.success(clothingSalesService.getClothingSalesUser(clothingSalesId));
}

@Operation(summary = "์–ด๋“œ๋ฏผ ๋Œ€์‹œ๋ณด๋“œ - ์˜ท์žฅ ์ •๋ฆฌ ํ˜„ํ™ฉ",
description = "์ตœ๊ทผ 1๊ฐœ์›” ๊ธฐ์ค€")
@GetMapping("/count")
public SuccessResponse<GetClothingSalesCount> getClothingSalesCount() {
return SuccessResponse.success(clothingSalesService.getClothingSalesCount());
}

@Operation(summary = "์–ด๋“œ๋ฏผ ๋Œ€์‹œ๋ณด๋“œ - ์˜ค๋Š˜์˜ ํ˜„ํ™ฉ")
@GetMapping("/today")
public SuccessResponse<GetClothingSalesAndProductOrderCount> getCountToday() {
return SuccessResponse.success(clothingSalesService.getCountToday());
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.repick.domain.clothingSales.dto;

import io.swagger.v3.oas.annotations.media.Schema;

public record GetClothingSalesAndProductOrderCount(
@Schema(name = "์ˆ˜๊ฑฐ ์‹ ์ฒญ ์ˆ˜") int collectionRequestCount,
@Schema(name = "๊ฒฐ์ œ ์™„๋ฃŒ ์ˆ˜") int paymentCompleteCount,
@Schema(name = "๋ฐ˜ํ’ˆ ์š”์ฒญ ์ˆ˜") int returnRequestCount
) {
public static GetClothingSalesAndProductOrderCount of(int collectionRequestCount, int paymentCompleteCount, int returnRequestCount) {
return new GetClothingSalesAndProductOrderCount(collectionRequestCount, paymentCompleteCount, returnRequestCount);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.repick.domain.clothingSales.dto;

import io.swagger.v3.oas.annotations.media.Schema;

public record GetClothingSalesCount(
@Schema(name = "์ˆ˜๊ฑฐ ์‹ ์ฒญ ์ˆ˜") long collectionRequestCount,
@Schema(name = "์ƒํ’ˆํ™” ์ง„ํ–‰ ์ค‘ ์ˆ˜") long productionProgressCount,
@Schema(name = "์ƒํ’ˆํ™” ์™„๋ฃŒ ์ˆ˜") long productionCompleteCount,
@Schema(name = "ํŒ๋งค์ค‘ ์ˆ˜") long sellingCount,
@Schema(name = "์ •์‚ฐ ์š”์ฒญ ์ˆ˜") long settlementRequestCount

) {
public static GetClothingSalesCount of(long collectionRequestCount, long productionProgressCount, long productionCompleteCount, long sellingCount, long settlementRequestCount) {
return new GetClothingSalesCount(collectionRequestCount, productionProgressCount, productionCompleteCount, sellingCount, settlementRequestCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
import com.example.repick.domain.clothingSales.entity.ClothingSalesStateType;
import org.springframework.data.jpa.repository.JpaRepository;

import java.time.LocalDateTime;
import java.util.List;

public interface ClothingSalesStateRepository extends JpaRepository<ClothingSalesState, Long>{
List<ClothingSalesState> findByClothingSalesId(Long clothingSalesId);

boolean existsByClothingSalesIdAndClothingSalesStateType(Long id, ClothingSalesStateType bagDelivered);
List<ClothingSalesState> findByCreatedDateAfter(LocalDateTime createdDate);

int countByClothingSalesStateTypeInAndCreatedDateAfter(List<ClothingSalesStateType> clothingSalesStateTypes, LocalDateTime createdDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.example.repick.domain.clothingSales.validator.ClothingSalesValidator;
import com.example.repick.domain.product.entity.Product;
import com.example.repick.domain.product.entity.ProductOrder;
import com.example.repick.domain.product.entity.ProductOrderState;
import com.example.repick.domain.product.entity.ProductStateType;
import com.example.repick.domain.product.repository.ProductOrderRepository;
import com.example.repick.domain.product.repository.ProductRepository;
Expand Down Expand Up @@ -218,5 +219,34 @@ public GetClothingSalesUser getClothingSalesUser(Long clothingSalesId){
return GetClothingSalesUser.of(code, user);
}

public GetClothingSalesCount getClothingSalesCount() {
List<ClothingSalesState> clothingSalesStateList = clothingSalesStateRepository.findByCreatedDateAfter(LocalDateTime.now().minusMonths(1));
long collectionRequestCount = 0;
long productionProgressCount = 0;
long productionCompleteCount = 0;
long sellingCount = 0;
long settlementRequestCount = 0; // TODO: ์ •์‚ฐ ์š”์ฒญ ์ˆ˜ (์ •์‚ฐ๊ธˆ ์ถœ๊ธˆ ์‹ ์ฒญ ํ”Œ๋กœ์šฐ ๊ตฌํ˜„ ํ›„ ์ถ”๊ฐ€)
for (ClothingSalesState clothingSalesState : clothingSalesStateList) {
switch (clothingSalesState.getClothingSalesStateType()) {
case BOX_COLLECT_REQUEST, BAG_COLLECT_REQUEST -> collectionRequestCount++;
case COLLECTED, SHOOTING, SHOOTED, PRODUCTING -> productionProgressCount++;
case PRODUCTED, PRODUCT_REGISTERED -> productionCompleteCount++;
case SELLING -> sellingCount++;
}
}
return GetClothingSalesCount.of(collectionRequestCount, productionProgressCount, productionCompleteCount, sellingCount, settlementRequestCount);
}

public GetClothingSalesAndProductOrderCount getCountToday(){
int collectionRequestCount = clothingSalesStateRepository.countByClothingSalesStateTypeInAndCreatedDateAfter(
List.of(ClothingSalesStateType.BOX_COLLECT_REQUEST, ClothingSalesStateType.BAG_COLLECT_REQUEST),
LocalDate.now().atStartOfDay());
int paymentCompleteCount = productOrderRepository.countByProductOrderStateAndLastModifiedDateAfter(
ProductOrderState.PAYMENT_COMPLETED, LocalDate.now().atStartOfDay());
int returnRequestCount = productOrderRepository.countByProductOrderStateAndLastModifiedDateAfter(
ProductOrderState.RETURN_REQUESTED, LocalDate.now().atStartOfDay());
return GetClothingSalesAndProductOrderCount.of(collectionRequestCount, paymentCompleteCount, returnRequestCount);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,8 @@ public SuccessResponse<PageResponse<List<GetProductCountClothingSales>>> getProd
""")
@GetMapping("/{clothingSalesId}/{productState}")
public SuccessResponse<PageResponse<List<?>>> getProductsByUserClothingSales(@PathVariable Long clothingSalesId,
@PathVariable String productState,
@ParameterObject PageCondition pageCondition,
@RequestParam(required = false) Boolean isExpired) {
public SuccessResponse<PageResponse<List<?>>> getProductsByUserClothingSales(@PathVariable Long clothingSalesId, @PathVariable String productState,
@ParameterObject PageCondition pageCondition, @RequestParam(required = false) Boolean isExpired) {
return SuccessResponse.success(productService.getProductsByUserClothingSales(clothingSalesId, productState, isExpired, pageCondition));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,10 @@ public SuccessResponse<Boolean> updateProductOrderState(@Schema(description = "
return SuccessResponse.success(productOrderService.updateProductOrderState(productOrderId, productOrderSateRequest));
}

@Operation(summary = "์–ด๋“œ๋ฏผ ๋Œ€์‹œ๋ณด๋“œ - ๊ตฌ๋งค ํ˜„ํ™ฉ", description = "์ตœ๊ทผ 1๊ฐœ์›” ๊ธฐ์ค€")
@GetMapping("/count")
public SuccessResponse<GetProductOrderCount> getProductOrderCount() {
return SuccessResponse.success(productOrderService.getProductOrderCount());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.repick.domain.product.dto.productOrder;

import io.swagger.v3.oas.annotations.media.Schema;

public record GetProductOrderCount(
@Schema(name = "๊ตฌ๋งค ์š”์ฒญ ์ˆ˜") long paymentCompletedCount,
@Schema(name = "๋ฐœ์†ก ์ค‘ ์ˆ˜") long shippingCount,
@Schema(name = "๊ตฌ๋งค ํ™•์ • ๋Œ€๊ธฐ ์ˆ˜") long confirmWaitCount,
@Schema(name = "๊ตฌ๋งค ํ™•์ • ์ˆ˜") long confirmedCount,
@Schema(name = "๋ฐ˜ํ’ˆ ์š”์ฒญ ์ˆ˜") long returnRequestCount
) {
public static GetProductOrderCount of(long paymentCompletedCount, long shippingCount, long confirmWaitCount, long confirmedCount, long refundRequestCount) {
return new GetProductOrderCount(paymentCompletedCount, shippingCount, confirmWaitCount, confirmedCount, refundRequestCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.example.repick.global.error.exception.CustomException;
import com.example.repick.global.error.exception.ErrorCode;
import lombok.Getter;

@Getter
public enum QualityRate {
S(1, "S"),
A(2, "A"),
Expand All @@ -16,14 +18,6 @@ public enum QualityRate {
this.value = value;
}

public int getId() {
return id;
}

public String getValue() {
return value;
}

public static QualityRate fromId(int id) {
for (QualityRate qualityRate : values()) {
if (qualityRate.getId() == id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.data.jpa.repository.JpaRepository;

import javax.swing.text.html.Option;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

Expand All @@ -22,4 +23,7 @@ public interface ProductOrderRepository extends JpaRepository<ProductOrder, Long

Optional<ProductOrder> findFirstByProductIdOrderByCreatedDateDesc(Long productId);

List<ProductOrder> findByLastModifiedDateAfter(LocalDateTime localDateTime);
int countByProductOrderStateAndLastModifiedDateAfter(ProductOrderState productOrderState, LocalDateTime localDateTime);

}
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ public Page<GetReturnedProductClothingSales> getClothingSalesReturnedProduct(Lon
p.getProductCode(),
p.getThumbnailImageUrl(),
p.getProductName(),
p.getQualityRate().toString(),
p.getQualityRate() != null ? p.getQualityRate().getValue() : null,
p.getClothingSales().getReturnRequestDate().format(DateTimeFormatter.ofPattern("MM/dd/yy"))
))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

import static com.example.repick.global.error.exception.ErrorCode.*;
Expand Down Expand Up @@ -267,4 +268,28 @@ public Boolean updateProductOrderState(Long productOrderId, ProductOrderSateRequ
return true;
}

public GetProductOrderCount getProductOrderCount(){
List<ProductOrder> productOrders = productOrderRepository.findByLastModifiedDateAfter(LocalDateTime.now().minusMonths(1));
long paymentCompletedCount = 0;
long shippingCount = 0;
long confirmWaitCount = 0;
long confirmedCount = 0;
long refundRequestCount = 0;
for (ProductOrder productOrder : productOrders) {
switch (productOrder.getProductOrderState()) {
case PAYMENT_COMPLETED -> paymentCompletedCount++;
case SHIPPING -> shippingCount++;
case DELIVERED -> {
if (productOrder.isConfirmed()) {
confirmedCount++;
} else {
confirmWaitCount++;
}
}
case RETURN_REQUESTED -> refundRequestCount++;
}
}
return GetProductOrderCount.of(paymentCompletedCount, shippingCount, confirmWaitCount, confirmedCount, refundRequestCount);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@ public SuccessResponse<GetMyPage> getMyPage() {
return SuccessResponse.success(userService.getMyPage());
}

@Operation(summary = "์–ด๋“œ๋ฏผ ๋Œ€์‹œ๋ณด๋“œ - ์œ ์ € ํ†ต๊ณ„")
@GetMapping("/statistics")
public SuccessResponse<GetUserStatistics> getUserStatistics() {
return SuccessResponse.success(userService.getUserStatistics());
}

@Operation(summary = "ํ‘ธ์‹œ ์•Œ๋ฆผ ํ—ˆ์šฉ ์—ฌ๋ถ€ ์ˆ˜์ •ํ•˜๊ธฐ",
description = """
ํ‘ธ์‹œ ์•Œ๋ฆผ ํ—ˆ์šฉ ์—ฌ๋ถ€๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.repick.domain.user.dto;

import io.swagger.v3.oas.annotations.media.Schema;

public record GetUserStatistics(
@Schema(name = "์ด ์œ ์ € ์ˆ˜") long totalUserCount,
@Schema(name = "์‹ ๊ทœ ๊ฐ€์ž… ์œ ์ € ์ˆ˜") long newUserCount
){
public static GetUserStatistics of(long totalUserCount, long newUserCount) {
return new GetUserStatistics(totalUserCount, newUserCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import com.example.repick.domain.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.time.LocalDateTime;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {

Optional<User> findByProviderId(String providerId);

Long countByIsDeletedFalse();
Long countByIsDeletedFalseAndCreatedDateAfter(LocalDateTime createdDate);

}
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ public TokenResponse refreshToken(PostTokenRefresh postTokenRefresh) {
return new TokenResponse(accessToken, postTokenRefresh.refreshToken());
}

@Transactional(readOnly = true)
public GetMyPage getMyPage() {
User user = userRepository.findByProviderId(SecurityContextHolder.getContext().getAuthentication().getName())
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
Expand All @@ -185,6 +186,14 @@ public GetMyPage getMyPage() {
return GetMyPage.of(user.getNickname(), user.getSettlement(), preparing, shipping, delivered, confirmed);
}

@Transactional(readOnly = true)
public GetUserStatistics getUserStatistics() {
long totalUserCount = userRepository.countByIsDeletedFalse();
long newUserCount = userRepository.countByIsDeletedFalseAndCreatedDateAfter(LocalDateTime.now().minusMonths(1));
return GetUserStatistics.of(totalUserCount, newUserCount);
}

@Transactional
public Boolean updatePushAllow(boolean pushAllow) {
User user = userRepository.findByProviderId(SecurityContextHolder.getContext().getAuthentication().getName())
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
Expand Down

0 comments on commit 8339825

Please sign in to comment.