Skip to content

Commit

Permalink
feature: return/kg sell for rejected or expired products (#133)
Browse files Browse the repository at this point in the history
* feature: add updateProductReturnState api

* refactor: moved api location from clothingsales to product

* refactor: save salesStartDate in clothingSales

* fix: get products by userClothingSales api

* refactor: use generic type and separate dto

* chore: fix getProductsByUserClothingSales

* chore: add swagger doc

* chore: add swagger doc
  • Loading branch information
hyunihs authored Aug 11, 2024
1 parent a57597a commit bd6abdf
Show file tree
Hide file tree
Showing 19 changed files with 297 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.example.repick.domain.clothingSales.service.BagService;
import com.example.repick.domain.clothingSales.service.BoxService;
import com.example.repick.domain.clothingSales.service.ClothingSalesService;
import com.example.repick.domain.product.entity.ProductStateType;
import com.example.repick.global.page.DateCondition;
import com.example.repick.global.page.PageCondition;
import com.example.repick.global.page.PageResponse;
Expand Down Expand Up @@ -116,21 +115,6 @@ public SuccessResponse<Boolean> updateClothingSalesStatus(@RequestBody PostCloth
return SuccessResponse.success(clothingSalesService.updateClothingSalesState(postClothingSalesState));
}

@Operation(summary = "μƒν’ˆ μ’…ν•© ν˜„ν™©")
@GetMapping("/product-count")
public SuccessResponse<PageResponse<List<GetClothingSalesProductCount>>> getClothingSalesProductCount(@RequestParam(required = false) Long userId,
@ParameterObject PageCondition pageCondition) {
return SuccessResponse.success(clothingSalesService.getClothingSalesProductCount(userId, pageCondition));
}

@Operation(summary = "μœ μ € μƒν’ˆ ν˜„ν™©")
@GetMapping("/products/{clothingSalesId}/{productStateType}")
public SuccessResponse<PageResponse<List<GetClothingSalesProduct>>> getClothingSalesProduct(@PathVariable Long clothingSalesId,
@PathVariable ProductStateType productStateType,
@ParameterObject PageCondition pageCondition) {
return SuccessResponse.success(clothingSalesService.getClothingSalesProduct(clothingSalesId, productStateType, pageCondition));
}

@Operation(summary = "옷μž₯ 정리 μƒν’ˆ 무게 등둝")
@PatchMapping("/weight")
public SuccessResponse<Boolean> updateClothingSalesWeight(@RequestBody PatchClothingSalesWeight patchClothingSalesWeight) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ public static GetClothingSales of(ClothingSales clothingSales) {
.status(clothingSalesState.getAdminValue())
.requestDate(clothingSales.getCreatedDate().format(formatter))
.isForCollect(!ClothingSalesStateType.BEFORE_COLLECTION.contains(clothingSalesState))
.productStartDate(isSelling? clothingSales.getProductList().get(0).getSalesStartDate().format(formatter) : null)
.salesPeriod(isSelling? clothingSales.getProductList().get(0).getSalesStartDate().format(formatter)
+ " ~ " + clothingSales.getProductList().get(0).getSalesStartDate().plusDays(90).format(formatter) : null)
.productStartDate(isSelling? clothingSales.getSalesStartDate().format(formatter) : null)
.salesPeriod(isSelling? clothingSales.getSalesStartDate().format(formatter)
+ " ~ " + clothingSales.getSalesStartDate().plusDays(90).format(formatter) : null)
.settlementRequestDate(clothingSales.getUser().getSettlementRequestDate() != null ? clothingSales.getUser().getSettlementRequestDate().format(formatter) : null)
.settlementCompleteDate(clothingSales.getUser().getSettlementCompleteDate() != null ? clothingSales.getUser().getSettlementCompleteDate().format(formatter) : null)
.isRejected(isProducted? clothingSales.getProductList().stream().anyMatch(product -> product.getProductState() == ProductStateType.REJECTED) : null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public abstract class ClothingSales {
@OneToMany(mappedBy = "clothingSales")
private List<Product> productList;

private LocalDateTime salesStartDate; // 판맀 μ‹œμž‘μΌ
private LocalDateTime returnRequestDate; // kg λ§€μž…μš”μ²­/λ°˜μ†‘ μš”μ²­μΌ

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
Expand Down Expand Up @@ -94,4 +97,12 @@ public void updateBagCollectInfo(Integer bagQuantity, String postalCode, String
this.address = new Address(postalCode, mainAddress, detailAddress);
this.collectionDate = LocalDate.parse(collectionDate);
}

public void updateSalesStartDate(LocalDateTime salesStartDate) {
this.salesStartDate = salesStartDate;
}

public void updateReturnRequestDate(LocalDateTime returnRequestDate) {
this.returnRequestDate = returnRequestDate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

public interface ClothingSalesRepository extends JpaRepository<ClothingSales, Long> {
Page<ClothingSales> findAllByOrderByCreatedDateDesc(Pageable pageable);
List<ClothingSales> findByClothingSalesState(ClothingSalesStateType clothingSalesStateType);
List<ClothingSales> findByUserAndClothingSalesState(User user, ClothingSalesStateType clothingSalesStateType);
Page<ClothingSales> findByCreatedDateBetweenOrderByCreatedDateDesc(LocalDateTime startDate, LocalDateTime endDate, Pageable pageable);
List<ClothingSales> findByUserOrderByCreatedDateDesc(User user);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,6 @@ public class ClothingSalesService {
private final ClothingSalesStateRepository clothingSalesStateRepository;
private final ProductOrderRepository productOrderRepository;

public void updateSellingExpired(Product product) {
ClothingSalesState clothingSalesState = ClothingSalesState.of(product.getClothingSales().getId(), ClothingSalesStateType.SELLING_EXPIRED);
clothingSalesStateRepository.save(clothingSalesState);
}

public List<GetPendingClothingSales> getPendingClothingSales() {
User user = userRepository.findByProviderId(SecurityContextHolder.getContext().getAuthentication().getName())
.orElseThrow(() -> new CustomException(USER_NOT_FOUND));
Expand Down Expand Up @@ -96,14 +91,14 @@ public Boolean updateProductPrice(List<PostProductPrice> postProductPriceList) {
productList.forEach(product -> {
productService.calculateDiscountPriceAndPredictDiscountRateAndSave(product);
productService.changeSellingState(product, ProductStateType.SELLING);
product.updateSalesStartDate(LocalDateTime.now());
});
productRepository.saveAll(productList);

ClothingSales clothingSales = productList.get(0).getClothingSales();
ClothingSalesState clothingSalesState = ClothingSalesState.of(clothingSales.getId(), ClothingSalesStateType.SELLING);
clothingSalesStateRepository.save(clothingSalesState);
clothingSales.updateClothingSalesState(ClothingSalesStateType.SELLING);
clothingSales.updateSalesStartDate(LocalDateTime.now());
clothingSalesRepository.save(clothingSales);

return true;
Expand All @@ -121,8 +116,7 @@ public List<GetSellingClothingSales> getSellingClothingSales() {
if(productList.isEmpty()) {
continue;
}
LocalDateTime salesStartDate = productList.get(0).getSalesStartDate();
int remainingSalesDays = (int) ChronoUnit.DAYS.between(LocalDate.now(), salesStartDate.toLocalDate().plusDays(90));
int remainingSalesDays = (int) ChronoUnit.DAYS.between(LocalDate.now(), clothingSales.getSalesStartDate().toLocalDate().plusDays(90));
int sellingQuantity = 0;
int pendingQuantity = 0;
int soldQuantity = 0;
Expand All @@ -139,7 +133,7 @@ public List<GetSellingClothingSales> getSellingClothingSales() {
}
}
}
sellingClothingSalesList.add(GetSellingClothingSales.of(clothingSales, salesStartDate.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")), remainingSalesDays, sellingQuantity, pendingQuantity, soldQuantity));
sellingClothingSalesList.add(GetSellingClothingSales.of(clothingSales, clothingSales.getSalesStartDate().format(DateTimeFormatter.ofPattern("yyyy.MM.dd")), remainingSalesDays, sellingQuantity, pendingQuantity, soldQuantity));
}
return sellingClothingSalesList;

Expand Down Expand Up @@ -208,12 +202,6 @@ public Boolean updateClothingSalesState(PostClothingSalesState postClothingSales
return true;
}

@Transactional
public PageResponse<List<GetClothingSalesProductCount>> getClothingSalesProductCount(Long userId, PageCondition pageCondition) {
Page<GetClothingSalesProductCount> pages = productRepository.getClothingSalesProductCount(pageCondition.toPageable(), userId);
return PageResponse.of(pages.getContent(), pages.getTotalPages(), pages.getTotalElements());
}

@Transactional
public void updateClothingSalesWeight(PatchClothingSalesWeight patchClothingSalesWeight) {
ClothingSales clothingSales = clothingSalesRepository.findById(patchClothingSalesWeight.clothingSalesId())
Expand All @@ -222,17 +210,6 @@ public void updateClothingSalesWeight(PatchClothingSalesWeight patchClothingSale
clothingSalesRepository.save(clothingSales);
}

public PageResponse<List<GetClothingSalesProduct>> getClothingSalesProduct(Long clothingSalesId, ProductStateType productStateType, PageCondition pageCondition) {
Page<GetClothingSalesProduct> pages;
if (productStateType == ProductStateType.SELLING || productStateType == ProductStateType.SOLD_OUT) {
pages = productRepository.getClothingSalesPendingProduct(clothingSalesId, productStateType, pageCondition.toPageable());
}
else {
pages = productRepository.getClothingSalesCancelledProduct(clothingSalesId, productStateType, pageCondition.toPageable());
}
return PageResponse.of(pages.getContent(), pages.getTotalPages(), pages.getTotalElements());
}

public GetClothingSalesUser getClothingSalesUser(Long clothingSalesId){
ClothingSales clothingSales = clothingSalesRepository.findById(clothingSalesId)
.orElseThrow(() -> new CustomException(INVALID_CLOTHING_SALES_ID));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.repick.domain.product.api;

import com.example.repick.domain.product.dto.productClothingSales.GetProductCountClothingSales;
import com.example.repick.domain.product.dto.product.*;
import com.example.repick.domain.product.dto.productOrder.GetProductCart;
import com.example.repick.domain.product.service.ProductService;
Expand Down Expand Up @@ -214,4 +215,45 @@ public SuccessResponse<GetProductDetail> getProductDetail(
return SuccessResponse.success(productService.getProductDetail(productId));
}

@Operation(summary = "μƒν’ˆ 리턴 μƒνƒœ λ³€κ²½",
description = """
μƒν’ˆ 리턴 μƒνƒœ 변경은 λ‹€μŒ μƒν™©μ—μ„œ μ‚¬μš©ν•©λ‹ˆλ‹€:
(리젝된 경우, 만료된 경우)
μ‚¬μš©μž: kg λ§€μž… μ‹ μ²­/λŒλ €λ°›κΈ° μ‹ μ²­
κ΄€λ¦¬μž: λ°˜μ†‘ μ™„λ£Œ μ—…λ°μ΄νŠΈ
**returnState: kg λ§€μž…, λ°˜μ†‘ μš”μ²­, λ°˜μ†‘ μ™„λ£Œ**
""")
@PatchMapping("/return")
public SuccessResponse<Boolean> patchProductReturn(@RequestBody PatchProductReturn patchProductReturn) {
return SuccessResponse.success(productService.updateProductReturnState(patchProductReturn));
}

@Operation(summary = "μƒν’ˆ μ’…ν•© ν˜„ν™©")
@GetMapping("/count")
public SuccessResponse<PageResponse<List<GetProductCountClothingSales>>> getProductCountByClothingSales(@RequestParam(required = false) Long userId,
@ParameterObject PageCondition pageCondition) {
return SuccessResponse.success(productService.getProductCountByClothingSales(userId, pageCondition));
}

@Operation(summary = "μœ μ € μƒν’ˆ ν˜„ν™©",
description = """
productState: selling, sold-out, rejected, selling-end, kg-sell
isExpired: kg λ§€μž… ν™”λ©΄μ—μ„œλ§Œ μ‚¬μš© (true: 만료된 μƒν’ˆ 쑰회, false: 리젝 μƒν’ˆ 쑰회)
""")
@GetMapping("/{clothingSalesId}/{productState}")
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));
}

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

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

import java.util.List;

public record PatchProductReturn(
@Schema(description = "λ°˜ν’ˆ μƒνƒœ") String returnState,
@Schema(description = "μƒν’ˆ id λͺ©λ£") List<Long> productIds
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.repick.domain.product.dto.productClothingSales;

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

public record GetKgSellProductClothingSales(
@Schema(description = "μƒν’ˆμ½”λ“œ") String productCode,
@Schema(description = "썸넀일") String thumbnailImageUrl,
@Schema(description = "μƒν’ˆλͺ…") String productName,
@Schema(description = "λ“±κΈ‰") String grade,
@Schema(description = "신청일") String requestDate,
@Schema(description = "만료 μ—¬λΆ€ (kg λ§€μž… 경둜용)") Boolean isExpired,
@Schema(description = "kg λ§€μž… μ •μ‚° μƒνƒœ") Boolean settlementStatus
) {
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.example.repick.domain.clothingSales.dto;
package com.example.repick.domain.product.dto.productClothingSales;

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

import java.time.LocalDateTime;

public record GetClothingSalesProductCount (
public record GetProductCountClothingSales(
@Schema(description = "μ½”λ“œ") String code,
@Schema(description = "이름") String name,
@Schema(description = "μœ μ € ID") Long userId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
package com.example.repick.domain.clothingSales.dto;
package com.example.repick.domain.product.dto.productClothingSales;

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

public record GetClothingSalesProduct(
public record GetProductsClothingSales(
@Schema(description = "μƒν’ˆμ½”λ“œ") String productCode,
@Schema(description = "썸넀일") String thumbnailImageUrl,
@Schema(description = "μƒν’ˆλͺ…") String productName,
@Schema(description = "λ“±κΈ‰") String grade,
@Schema(description = "νŒλ§€κΈ°κ°„") String salesPeriod,
@Schema(description = "판맀 κΈˆμ•‘") Long salesPrice,
@Schema(description = "μ •μ‚°κΈˆ") Long settlementPrice,
@Schema(description = "수수료") Long fee,
@Schema(description = "신청일") String requestDate,
@Schema(description = "λ°˜μ†‘ μ—¬λΆ€") Boolean isReturned
@Schema(description = "수수료") Long fee
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.repick.domain.product.dto.productClothingSales;

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

public record GetReturnedProductClothingSales(
@Schema(description = "μƒν’ˆμ½”λ“œ") String productCode,
@Schema(description = "썸넀일") String thumbnailImageUrl,
@Schema(description = "μƒν’ˆλͺ…") String productName,
@Schema(description = "λ“±κΈ‰") String grade,
@Schema(description = "신청일") String requestDate
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

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

@Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter
Expand Down Expand Up @@ -46,9 +45,10 @@ public class Product extends BaseEntity {
private Gender gender;
@Column(length = 1000)
private String thumbnailImageUrl;
private LocalDateTime salesStartDate;
@Enumerated(EnumType.STRING)
private ProductStateType productState;
@Enumerated(EnumType.STRING)
private ProductReturnStateType returnState; // λ¦¬μ λ˜κ±°λ‚˜ 만료된 μƒν’ˆμ˜ μƒνƒœ
private long settlement; // μ •μ‚°κΈˆ

@OneToMany(mappedBy = "product", cascade = CascadeType.ALL)
Expand Down Expand Up @@ -162,14 +162,14 @@ public void updateThumbnailImageUrl(String thumbnailImageUrl) {
this.thumbnailImageUrl = thumbnailImageUrl;
}

public void updateSalesStartDate(LocalDateTime salesStartDate) {
this.salesStartDate = salesStartDate;
}

public void updateProductState(ProductStateType productState) {
this.productState = productState;
}

public void updateReturnState(ProductReturnStateType returnState) {
this.returnState = returnState;
}

public void updateSettlement(long settlement) {
this.settlement = settlement;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.example.repick.domain.product.entity;

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

@Getter
public enum ProductReturnStateType {
KG_SELL(1, "KG λ§€μž…"),
RETURN_REQUESTED(2, "λ°˜μ†‘ μš”μ²­"),
RETURN_COMPLETED(3, "λ°˜μ†‘ μ™„λ£Œ");

private final int id;
private final String value;

ProductReturnStateType(int id, String value) {
this.id = id;
this.value = value;
}

public static ProductReturnStateType fromValue(String keyword) {
for (ProductReturnStateType productReturnStateType : values()) {
if (productReturnStateType.getValue().equals(keyword)) {
return productReturnStateType;
}
}
throw new CustomException(ErrorCode.INVALID_PRODUCT_RETURN_STATE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@
@Getter
public enum ProductStateType {

PREPARING(1, "νŒλ§€μ€€λΉ„μ€‘"),
SELLING(2, "νŒλ§€μ€‘"),
SOLD_OUT(3, "νŒλ§€μ™„λ£Œ"),
SETTLING(4, "정산쀑"),
SETTLED(5, "μ •μ‚°μ™„λ£Œ"),
REJECTED(6, "리젝됨"),
SELLING_END(7, "νŒλ§€μ’…λ£Œ"),
RETURN_REQUESTED(8, "λ°˜ν’ˆμš”μ²­λ¨");
PREPARING(1, "νŒλ§€μ€€λΉ„μ€‘", "preparing"),
SELLING(2, "νŒλ§€μ€‘", "selling"),
SOLD_OUT(3, "νŒλ§€μ™„λ£Œ", "sold-out"),
SETTLING(4, "정산쀑", "settling"),
SETTLED(5, "μ •μ‚°μ™„λ£Œ", "settled"),
REJECTED(6, "리젝됨", "rejected"),
SELLING_END(7, "νŒλ§€μ’…λ£Œ", "selling-end"),
RETURN_REQUESTED(8, "λ°˜ν’ˆμš”μ²­λ¨", "return-requested");

private final int id;
private final String value;
private final String engValue;

ProductStateType(int id, String value) {
ProductStateType(int id, String value, String engValue) {
this.id = id;
this.value = value;
this.engValue = engValue;
}

public static ProductStateType fromId(int id) {
Expand All @@ -41,4 +43,13 @@ public static ProductStateType fromValue(String keyword) {
}
throw new CustomException(ErrorCode.INVALID_SELLING_STATE_NAME);
}

public static ProductStateType fromEngValue(String keyword) {
for (ProductStateType productStateType : values()) {
if (productStateType.getEngValue().equals(keyword)) {
return productStateType;
}
}
throw new CustomException(ErrorCode.INVALID_SELLING_STATE_NAME);
}
}
Loading

0 comments on commit bd6abdf

Please sign in to comment.