diff --git a/db/src/main/java/db/domain/fault/FaultEntity.java b/db/src/main/java/db/domain/fault/FaultEntity.java index eaf66274..e894dd3e 100644 --- a/db/src/main/java/db/domain/fault/FaultEntity.java +++ b/db/src/main/java/db/domain/fault/FaultEntity.java @@ -20,11 +20,14 @@ @AllArgsConstructor public class FaultEntity extends BaseEntity { - private LocalDateTime guaranteeAt; - @Column(length = 200, nullable = false) private String description; + @Column(nullable = false) + private Boolean approval; + + private LocalDateTime registeredAt; + @Column(nullable = false) private Long receivingId; diff --git a/db/src/main/java/db/domain/fault/FaultRepository.java b/db/src/main/java/db/domain/fault/FaultRepository.java index 4cf3f5e1..66e55e40 100644 --- a/db/src/main/java/db/domain/fault/FaultRepository.java +++ b/db/src/main/java/db/domain/fault/FaultRepository.java @@ -4,4 +4,6 @@ public interface FaultRepository extends JpaRepository { + boolean existsByReceivingId(Long receivingId); + } diff --git a/db/src/main/java/db/domain/goods/GoodsRepository.java b/db/src/main/java/db/domain/goods/GoodsRepository.java index 66f23efc..b2e2dc12 100644 --- a/db/src/main/java/db/domain/goods/GoodsRepository.java +++ b/db/src/main/java/db/domain/goods/GoodsRepository.java @@ -19,4 +19,5 @@ public interface GoodsRepository extends JpaRepository { List findAllByShippingIdOrderByIdDesc(Long takeBackId); + List findAllByStatusOrderByIdDesc(GoodsStatus status); } diff --git a/db/src/main/java/db/domain/image/ImageRepository.java b/db/src/main/java/db/domain/image/ImageRepository.java index f784ec77..d892b6ef 100644 --- a/db/src/main/java/db/domain/image/ImageRepository.java +++ b/db/src/main/java/db/domain/image/ImageRepository.java @@ -10,4 +10,8 @@ public interface ImageRepository extends JpaRepository { Optional findFirstByIdOrderByIdDesc(Long imageId); + List findAllByImageMappingIdOrderByImageMappingId(Long id); + + Optional findFirstByImageMappingIdOrderByIdDesc(Long imageMappingId); + } diff --git a/db/src/main/java/db/domain/store/GoodsLedgerEntity.java b/db/src/main/java/db/domain/store/GoodsLedgerEntity.java new file mode 100644 index 00000000..30845136 --- /dev/null +++ b/db/src/main/java/db/domain/store/GoodsLedgerEntity.java @@ -0,0 +1,34 @@ +package db.domain.store; + +import db.domain.store.enums.StoreLocation; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "goods_ledger") +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class GoodsLedgerEntity { + + @Id + private Long goodsId; + + @Enumerated(EnumType.STRING) + @Column(length = 50,columnDefinition = "VARCHAR(50)") + private StoreLocation location; + + @Column(nullable = false) + private LocalDateTime storedDate; + +} diff --git a/db/src/main/java/db/domain/store/GoodsLedgerRepository.java b/db/src/main/java/db/domain/store/GoodsLedgerRepository.java new file mode 100644 index 00000000..bd50ccb4 --- /dev/null +++ b/db/src/main/java/db/domain/store/GoodsLedgerRepository.java @@ -0,0 +1,9 @@ +package db.domain.store; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface GoodsLedgerRepository extends JpaRepository { + +} diff --git a/db/src/main/java/db/domain/store/enums/StoreLocation.java b/db/src/main/java/db/domain/store/enums/StoreLocation.java new file mode 100644 index 00000000..7c8d6b89 --- /dev/null +++ b/db/src/main/java/db/domain/store/enums/StoreLocation.java @@ -0,0 +1,19 @@ +package db.domain.store.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum StoreLocation { + + S1( "서울"), + S2( "부산"), + S3("대구"), + S4( "대전"), + S5( "목포"), + ; + + private final String location; + +} diff --git a/db/src/main/java/db/domain/usedgoods/EntitySearchCondition.java b/db/src/main/java/db/domain/usedgoods/EntitySearchCondition.java index 66a22361..c00eeae6 100644 --- a/db/src/main/java/db/domain/usedgoods/EntitySearchCondition.java +++ b/db/src/main/java/db/domain/usedgoods/EntitySearchCondition.java @@ -1,5 +1,6 @@ package db.domain.usedgoods; +import db.domain.usedgoods.enums.UsedGoodsStatus; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; @@ -15,6 +16,7 @@ public class EntitySearchCondition { private Long usedGoodsId; private String keyword; + private UsedGoodsStatus status; private int minPrice; private Integer maxPrice; private LocalDateTime startDate; diff --git a/db/src/main/java/db/domain/usedgoods/QueryUsedGoodsRepository.java b/db/src/main/java/db/domain/usedgoods/QueryUsedGoodsRepository.java index 7e6e2344..bc59d036 100644 --- a/db/src/main/java/db/domain/usedgoods/QueryUsedGoodsRepository.java +++ b/db/src/main/java/db/domain/usedgoods/QueryUsedGoodsRepository.java @@ -33,7 +33,8 @@ public List usedGoodsSearchBy(EntitySearchCondition condition) loeEndDate(condition.getEndDate()), // endDate 이전 날짜로 조회 진행함 ltUsedGoodsId(condition.getUsedGoodsId()), // cursor 방식 적용 isNotUnregistered(), - isUserId(condition.getUserId()) + isUserId(condition.getUserId()), + filterBy(condition.getStatus()) // 파라미터로 받은 status로 필터링 ) .orderBy(getOrderSpecifier(condition.getPage().getSort()).stream() .toArray(size -> new OrderSpecifier[size])) @@ -85,4 +86,9 @@ private BooleanExpression isUserId(Long userId) { return userId != null ? usedGoodsEntity.userId.eq(userId) : null; } + private BooleanExpression filterBy(UsedGoodsStatus status) { + return status != null ? usedGoodsEntity.status.eq(status) + : usedGoodsEntity.status.ne(UsedGoodsStatus.UNREGISTERED); + } + } \ No newline at end of file diff --git a/db/src/main/java/db/domain/usedgoods/enums/UsedGoodsStatus.java b/db/src/main/java/db/domain/usedgoods/enums/UsedGoodsStatus.java index eea39638..c3cada48 100644 --- a/db/src/main/java/db/domain/usedgoods/enums/UsedGoodsStatus.java +++ b/db/src/main/java/db/domain/usedgoods/enums/UsedGoodsStatus.java @@ -9,10 +9,6 @@ public enum UsedGoodsStatus { REGISTERED(1, "중고 물품 등록", "판매 중인 중고 물품입니다."), UNREGISTERED(2, "중고 물품 취소", "판매 취소된 중고 물품입니다."), - DEALING(3, "중고 거래 중", "현재 거래 중인 중고 물품입니다."), - DEAL(4, "중고 거래 확정", "거래가 확정된 중고 물품입니다."), - REMITTANCE(5, "송금 확인", "송금이 확인되었습니다."), - ASSIGNMENT(6, "물건 확인", "물건이 확인되었습니다."), SOLD(7, "중고 거래 완료", "중고 물품 거래가 완료되었습니다.") ; diff --git a/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderEntity.java b/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderEntity.java index ac048de3..246be765 100644 --- a/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderEntity.java +++ b/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderEntity.java @@ -1,11 +1,8 @@ package db.domain.usedgoodsorder; import db.common.BaseEntity; -import db.domain.usedgoodsorder.enums.UsedGoodsOrderStatus; import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; import jakarta.persistence.Table; import java.time.LocalDateTime; import lombok.AllArgsConstructor; @@ -25,11 +22,10 @@ public class UsedGoodsOrderEntity extends BaseEntity { @Column(nullable = false) - private Long userId; // 구매자 ID + private Long buyerId; // 구매자 ID - @Enumerated(EnumType.STRING) - @Column(nullable = false, length = 50,columnDefinition = "VARCHAR(50)") - private UsedGoodsOrderStatus status; + @Column(nullable = false) + private Long sellerId; // 판매자 ID private LocalDateTime createdAt; diff --git a/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderRepository.java b/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderRepository.java index b2eb37fe..ed74b3fd 100644 --- a/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderRepository.java +++ b/db/src/main/java/db/domain/usedgoodsorder/UsedGoodsOrderRepository.java @@ -8,8 +8,12 @@ public interface UsedGoodsOrderRepository extends JpaRepository findAllByUsedGoodsId(Long usedGoodsId); + List findAllBySellerId(Long userId); + + List findAllByBuyerId(Long userId); + Optional findFirstById(Long usedGoodsOrderId); - Optional findByUsedGoodsIdAndUserId(Long usedGoodsId, Long userId); + Optional findByUsedGoodsIdAndBuyerId(Long usedGoodsId, Long buyerId); } diff --git a/db/src/main/java/db/domain/usedgoodsorder/enums/UsedGoodsOrderStatus.java b/db/src/main/java/db/domain/usedgoodsorder/enums/UsedGoodsOrderStatus.java deleted file mode 100644 index e857df86..00000000 --- a/db/src/main/java/db/domain/usedgoodsorder/enums/UsedGoodsOrderStatus.java +++ /dev/null @@ -1,20 +0,0 @@ -package db.domain.usedgoodsorder.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum UsedGoodsOrderStatus { - - REGISTERED(1, "거래 요청", "거래를 요청하였습니다."), - APPROVED(2, "거래 승인", "거래가 승인되었습니다."), - HOLD(3, "거래 보류", "거래가 보류되었습니다.") - ; - - private final int current; - private final String status; - private final String description; - - -} diff --git a/delivery/src/main/java/delivery/common/exception/ImageExceptionHandler.java b/delivery/src/main/java/delivery/common/exception/ImageExceptionHandler.java new file mode 100644 index 00000000..7abe0b10 --- /dev/null +++ b/delivery/src/main/java/delivery/common/exception/ImageExceptionHandler.java @@ -0,0 +1,33 @@ +package delivery.common.exception; + +import delivery.common.error.ImageErrorCode; +import delivery.common.exception.image.ImageNotFoundException; +import delivery.common.exception.image.ImageStorageException; +import global.api.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +@Order(value = Integer.MIN_VALUE) +public class ImageExceptionHandler { + + @ExceptionHandler(value = ImageStorageException.class) + public ResponseEntity> imageException(ImageStorageException e) { + log.info("", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(Api.ERROR(ImageErrorCode.IMAGE_STORAGE_ERROR)); + } + + @ExceptionHandler(value = ImageNotFoundException.class) + public ResponseEntity> imageException(ImageNotFoundException e) { + log.info("", e); + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(Api.ERROR(ImageErrorCode.IMAGE_NOT_FOUND)); + } + +} diff --git a/delivery/src/main/java/delivery/common/exception/image/ApiExceptionIfs.java b/delivery/src/main/java/delivery/common/exception/image/ApiExceptionIfs.java new file mode 100644 index 00000000..64bb7a6f --- /dev/null +++ b/delivery/src/main/java/delivery/common/exception/image/ApiExceptionIfs.java @@ -0,0 +1,11 @@ +package delivery.common.exception.image; + +import global.errorcode.ErrorCodeIfs; + +public interface ApiExceptionIfs { + + ErrorCodeIfs getErrorCodeIfs(); + + String getDescription(); + +} diff --git a/delivery/src/main/java/delivery/common/exception/image/ImageNotFoundException.java b/delivery/src/main/java/delivery/common/exception/image/ImageNotFoundException.java new file mode 100644 index 00000000..24102f13 --- /dev/null +++ b/delivery/src/main/java/delivery/common/exception/image/ImageNotFoundException.java @@ -0,0 +1,38 @@ +package delivery.common.exception.image; + +import global.errorcode.ErrorCodeIfs; +import lombok.Getter; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@Getter +@ResponseStatus(HttpStatus.NOT_FOUND) +public class ImageNotFoundException extends RuntimeException implements ApiExceptionIfs { + + private final ErrorCodeIfs errorCodeIfs; + private final String description; + + public ImageNotFoundException(ErrorCodeIfs errorCodeIfs) { + super(errorCodeIfs.getDescription()); + this.errorCodeIfs = errorCodeIfs; + this.description = errorCodeIfs.getDescription(); + } + + public ImageNotFoundException(ErrorCodeIfs errorCodeIfs, String errorDescription) { + this.errorCodeIfs = errorCodeIfs; + this.description = errorDescription; + } + + public ImageNotFoundException(ErrorCodeIfs errorCodeIfs, Throwable throwable) { + super(throwable); + this.errorCodeIfs = errorCodeIfs; + this.description = errorCodeIfs.getDescription(); + } + + public ImageNotFoundException(ErrorCodeIfs errorCodeIfs, Throwable throwable, + String errorDescription) { + super(throwable); + this.errorCodeIfs = errorCodeIfs; + this.description = errorDescription; + } +} diff --git a/delivery/src/main/java/delivery/common/exception/image/ImageStorageException.java b/delivery/src/main/java/delivery/common/exception/image/ImageStorageException.java new file mode 100644 index 00000000..930162e8 --- /dev/null +++ b/delivery/src/main/java/delivery/common/exception/image/ImageStorageException.java @@ -0,0 +1,36 @@ +package delivery.common.exception.image; + +import global.errorcode.ErrorCodeIfs; +import lombok.Getter; + +@Getter +public class ImageStorageException extends RuntimeException implements ApiExceptionIfs { + + private final ErrorCodeIfs errorCodeIfs; + private final String description; + + public ImageStorageException(ErrorCodeIfs errorCodeIfs) { + super(errorCodeIfs.getDescription()); + this.errorCodeIfs = errorCodeIfs; + this.description = errorCodeIfs.getDescription(); + } + + public ImageStorageException(ErrorCodeIfs errorCodeIfs, String errorDescription) { + this.errorCodeIfs = errorCodeIfs; + this.description = errorDescription; + } + + public ImageStorageException(ErrorCodeIfs errorCodeIfs, Throwable throwable) { + super(throwable); + this.errorCodeIfs = errorCodeIfs; + this.description = errorCodeIfs.getDescription(); + } + + public ImageStorageException(ErrorCodeIfs errorCodeIfs, Throwable throwable, + String errorDescription) { + super(throwable); + this.errorCodeIfs = errorCodeIfs; + this.description = errorDescription; + } + +} diff --git a/delivery/src/main/java/delivery/domain/image/converter/ImageConverter.java b/delivery/src/main/java/delivery/domain/image/converter/ImageConverter.java index 0b610181..ecec0d28 100644 --- a/delivery/src/main/java/delivery/domain/image/converter/ImageConverter.java +++ b/delivery/src/main/java/delivery/domain/image/converter/ImageConverter.java @@ -1,13 +1,19 @@ package delivery.domain.image.converter; import db.domain.image.ImageEntity; +import db.domain.imagemapping.ImageMappingEntity; import delivery.domain.goods.controller.model.ImageSet; +import delivery.domain.image.service.ImageMappingService; import global.annotation.Converter; import java.util.List; +import lombok.RequiredArgsConstructor; @Converter +@RequiredArgsConstructor public class ImageConverter { + private final ImageMappingService imageMappingService; + public List toImageSetList(List imageEntityList) { return imageEntityList.stream().map(imageEntity -> { return toImageSet(imageEntity); @@ -15,9 +21,12 @@ public List toImageSetList(List imageEntityList) { } public ImageSet toImageSet(ImageEntity imageEntity) { + ImageMappingEntity imageMappingEntity = imageMappingService.getImageMappingBy( + imageEntity.getImageMappingId()); return ImageSet.builder() .imageId(imageEntity.getId()) .caption(imageEntity.getCaption()) + .kind(imageMappingEntity.getKind()) .build(); } diff --git a/delivery/src/main/java/delivery/domain/image/service/ImageMappingService.java b/delivery/src/main/java/delivery/domain/image/service/ImageMappingService.java new file mode 100644 index 00000000..597ba0a8 --- /dev/null +++ b/delivery/src/main/java/delivery/domain/image/service/ImageMappingService.java @@ -0,0 +1,20 @@ +package delivery.domain.image.service; + +import db.domain.imagemapping.ImageMappingEntity; +import db.domain.imagemapping.ImageMappingRepository; +import delivery.common.error.ImageErrorCode; +import delivery.common.exception.image.ImageNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ImageMappingService { + + private final ImageMappingRepository imageMappingRepository; + + public ImageMappingEntity getImageMappingBy(Long imageMappingId) { + return imageMappingRepository.findById(imageMappingId) + .orElseThrow(() -> new ImageNotFoundException(ImageErrorCode.IMAGE_NOT_FOUND)); + } +} diff --git a/fault/src/main/java/fault/common/error/FaultErrorCode.java b/fault/src/main/java/fault/common/error/FaultErrorCode.java index e347ff79..5ba7fb0c 100644 --- a/fault/src/main/java/fault/common/error/FaultErrorCode.java +++ b/fault/src/main/java/fault/common/error/FaultErrorCode.java @@ -3,12 +3,13 @@ import global.errorcode.ErrorCodeIfs; import lombok.AllArgsConstructor; import lombok.Getter; +import org.springframework.http.HttpStatus; @Getter @AllArgsConstructor public enum FaultErrorCode implements ErrorCodeIfs { - + EXISTS_FAULT_REQUEST(HttpStatus.BAD_REQUEST.value(),1700,"등록된 결함 요총서가 존재합니다.") ; private final Integer httpCode; diff --git a/fault/src/main/java/fault/common/exception/FaultExceptionHandler.java b/fault/src/main/java/fault/common/exception/FaultExceptionHandler.java new file mode 100644 index 00000000..080cd49d --- /dev/null +++ b/fault/src/main/java/fault/common/exception/FaultExceptionHandler.java @@ -0,0 +1,23 @@ +package fault.common.exception; + +import fault.common.error.FaultErrorCode; +import fault.common.exception.fault.ExistsFaultRequestException; +import global.api.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class FaultExceptionHandler { + + @ExceptionHandler(value = ExistsFaultRequestException.class) + public ResponseEntity> existsFaultRequestException(ExistsFaultRequestException e) { + log.info("", e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Api.ERROR(FaultErrorCode.EXISTS_FAULT_REQUEST)); + } + +} diff --git a/fault/src/main/java/fault/common/exception/fault/ExistsFaultRequestException.java b/fault/src/main/java/fault/common/exception/fault/ExistsFaultRequestException.java new file mode 100644 index 00000000..a1097085 --- /dev/null +++ b/fault/src/main/java/fault/common/exception/fault/ExistsFaultRequestException.java @@ -0,0 +1,33 @@ +package fault.common.exception.fault; + +import global.errorcode.ErrorCodeIfs; + +public class ExistsFaultRequestException extends RuntimeException { + + private final ErrorCodeIfs errorCodeIfs; + private final String description; + + public ExistsFaultRequestException(ErrorCodeIfs errorCodeIfs) { + super(errorCodeIfs.getDescription()); + this.errorCodeIfs = errorCodeIfs; + this.description = errorCodeIfs.getDescription(); + } + + public ExistsFaultRequestException(ErrorCodeIfs errorCodeIfs, String errorDescription) { + this.errorCodeIfs = errorCodeIfs; + this.description = errorDescription; + } + + public ExistsFaultRequestException(ErrorCodeIfs errorCodeIfs, Throwable throwable) { + super(throwable); + this.errorCodeIfs = errorCodeIfs; + this.description = errorCodeIfs.getDescription(); + } + + public ExistsFaultRequestException(ErrorCodeIfs errorCodeIfs, Throwable throwable, + String errorDescription) { + super(throwable); + this.errorCodeIfs = errorCodeIfs; + this.description = errorDescription; + } +} diff --git a/fault/src/main/java/fault/domain/fault/business/FaultBusiness.java b/fault/src/main/java/fault/domain/fault/business/FaultBusiness.java index 692509e0..6f389552 100644 --- a/fault/src/main/java/fault/domain/fault/business/FaultBusiness.java +++ b/fault/src/main/java/fault/domain/fault/business/FaultBusiness.java @@ -7,15 +7,13 @@ import db.domain.imagemapping.ImageMappingEntity; import db.domain.receiving.ReceivingEntity; import db.domain.receiving.enums.ReceivingStatus; -import fault.domain.fault.controller.model.common.MessageResponse; import fault.domain.fault.controller.model.request.AddFaultRequest; -import fault.domain.fault.controller.model.request.RejectFaultRequest; +import fault.domain.fault.controller.model.request.FaultRequest; import fault.domain.fault.controller.model.response.AddFaultResponse; import fault.domain.fault.controller.model.response.FaultImageResponse; import fault.domain.fault.controller.model.response.FaultListResponse; -import fault.domain.fault.controller.model.response.RejectFaultResponse; +import fault.domain.fault.controller.model.response.FaultResponse; import fault.domain.fault.converter.FaultConverter; -import fault.domain.fault.converter.MessageConverter; import fault.domain.fault.service.FaultService; import fault.domain.goods.service.GoodsService; import fault.domain.image.service.ImageMappingService; @@ -37,13 +35,13 @@ public class FaultBusiness { private final GoodsService goodsService; private final FaultConverter faultConverter; - private final MessageConverter messageConverter; private final FaultService faultService; public FaultListResponse getFaultList(Long goodsId) { List faultImageMappingIdList = imageMappingService.getImageMappingIdByGoodsId(goodsId) .stream() - .filter(imageMappingEntity -> imageMappingEntity.getKind() == ImageKind.FAULT) + .filter(imageMappingEntity -> imageMappingEntity.getKind() == ImageKind.FAULT + || imageMappingEntity.getKind() == ImageKind.DELIVERY) .map(imageMappingEntity -> imageMappingEntity.getId()).toList(); List faultImageEntityList = imageService.getImageBy(faultImageMappingIdList); @@ -58,32 +56,42 @@ public FaultImageResponse getFaultDetail(Long imageId) { } - public MessageResponse approveFault(Long receivingId) { - receivingService.approveFault(receivingId); // **입고 상태를 DELIVERY 로 변경합니다.** - return messageConverter.toMassageResponse("결함이 승인되었습니다."); + public FaultResponse approveFault(FaultRequest faultRequest, String email) { + + Long userId = usersService.getUserWithThrow(email).getId(); + + // 이미 결함 승인/반려 기록이 있는경우 예외 + faultService.checkFaultRequest(faultRequest.getReceivingId()); + + approve(faultRequest); + + FaultEntity faultEntity = faultConverter.toEntity(faultRequest, userId); + + FaultEntity savedFaultEntity = faultService.approvalFault(faultEntity, true); + + return faultConverter.toResponse(savedFaultEntity); + } + public FaultResponse rejectFault(FaultRequest faultRequest, String email) { - public RejectFaultResponse rejectFault(RejectFaultRequest rejectFaultRequest, String email) { + Long userId = usersService.getUserWithThrow(email).getId(); - Long userId = usersService.getUserWithThrow(email).getId(); // deliveryManId + // 이미 결함 승인/반려 기록이 있는경우 예외 + faultService.checkFaultRequest(faultRequest.getReceivingId()); ReceivingEntity receivingEntity = receivingService.getReceivingBy( - rejectFaultRequest.getReceivingId()); + faultRequest.getReceivingId()); - // 결함 반려 - // **입고요청서 CLOSE, 물품 상태 REJECT** - receivingService.rejectFault(receivingEntity, ReceivingStatus.CLOSE); // - goodsService.findAllByReceivingIdWithThrow(receivingEntity.getId()).stream() - .forEach( - goodsEntity -> goodsService.setGoodsStatusBy(goodsEntity, GoodsStatus.REJECT) - ); + reject(receivingEntity); + + FaultEntity faultEntity = faultConverter.toEntity(faultRequest, userId); + + FaultEntity savedFaultEntity = faultService.approvalFault(faultEntity, false); - FaultEntity faultEntity = faultConverter.toEntity(rejectFaultRequest, userId); - FaultEntity savedFaultEntity = faultService.rejectFault(faultEntity); return faultConverter.toResponse(savedFaultEntity); - } + } public AddFaultResponse addFault(AddFaultRequest addFaultRequest, String email) { @@ -105,4 +113,17 @@ public AddFaultResponse addFault(AddFaultRequest addFaultRequest, String email) } + private void reject(ReceivingEntity receivingEntity) { + receivingService.rejectFault(receivingEntity, ReceivingStatus.CLOSE); // + goodsService.findAllByReceivingIdWithThrow(receivingEntity.getId()).stream() + .forEach( + goodsEntity -> goodsService.setGoodsStatusBy(goodsEntity, GoodsStatus.REJECT) + ); + } + + private void approve(FaultRequest faultRequest) { + receivingService.setReceivingStatusBy(faultRequest.getReceivingId(), + ReceivingStatus.DELIVERY); + } + } \ No newline at end of file diff --git a/fault/src/main/java/fault/domain/fault/controller/FaultApiController.java b/fault/src/main/java/fault/domain/fault/controller/FaultApiController.java index 1ecc5812..06806136 100644 --- a/fault/src/main/java/fault/domain/fault/controller/FaultApiController.java +++ b/fault/src/main/java/fault/domain/fault/controller/FaultApiController.java @@ -1,13 +1,12 @@ package fault.domain.fault.controller; import fault.domain.fault.business.FaultBusiness; -import fault.domain.fault.controller.model.common.MessageResponse; import fault.domain.fault.controller.model.request.AddFaultRequest; -import fault.domain.fault.controller.model.request.RejectFaultRequest; +import fault.domain.fault.controller.model.request.FaultRequest; import fault.domain.fault.controller.model.response.FaultImageResponse; import fault.domain.fault.controller.model.response.FaultListResponse; import fault.domain.fault.controller.model.response.AddFaultResponse; -import fault.domain.fault.controller.model.response.RejectFaultResponse; +import fault.domain.fault.controller.model.response.FaultResponse; import global.annotation.ApiValid; import global.api.Api; import io.swagger.v3.oas.annotations.Operation; @@ -44,26 +43,26 @@ public Api getFaultDetail(@PathVariable Long imageId) { return Api.OK(response); } - @PostMapping("/{receivingId}") + @PostMapping("/approve") @Operation(summary = "[결함 승인]") - public Api approveFault(@PathVariable Long receivingId) { - MessageResponse response = faultBusiness.approveFault(receivingId); + public Api approveFault(@RequestBody @ApiValid Api faultRequest, + @AuthenticationPrincipal User user) { + FaultResponse response = faultBusiness.approveFault(faultRequest.getBody(), + user.getUsername()); return Api.OK(response); } @PostMapping("/reject") @Operation(summary = "[결함 반려]") - public Api rejectFault( - @RequestBody @ApiValid Api rejectFaultRequest, + public Api rejectFault(@RequestBody @ApiValid Api faultRequest, @AuthenticationPrincipal User user) { - log.info("reject result : {}", rejectFaultRequest.toString()); - RejectFaultResponse response = faultBusiness.rejectFault(rejectFaultRequest.getBody(), + FaultResponse response = faultBusiness.rejectFault(faultRequest.getBody(), user.getUsername()); return Api.OK(response); } @PostMapping() - @Operation(summary = "[결함 추가 등록]") + @Operation(summary = "[결함 추가 등록]") // 배송자가 public Api addFault( @RequestBody @ApiValid Api addFaultRequest, @AuthenticationPrincipal User user) { diff --git a/fault/src/main/java/fault/domain/fault/controller/model/common/MessageResponse.java b/fault/src/main/java/fault/domain/fault/controller/model/common/MessageResponse.java deleted file mode 100644 index da2b8356..00000000 --- a/fault/src/main/java/fault/domain/fault/controller/model/common/MessageResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package fault.domain.fault.controller.model.common; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class MessageResponse { - - private String Message; - -} diff --git a/fault/src/main/java/fault/domain/fault/controller/model/request/RejectFaultRequest.java b/fault/src/main/java/fault/domain/fault/controller/model/request/FaultRequest.java similarity index 92% rename from fault/src/main/java/fault/domain/fault/controller/model/request/RejectFaultRequest.java rename to fault/src/main/java/fault/domain/fault/controller/model/request/FaultRequest.java index a8a3d6b1..1fa383de 100644 --- a/fault/src/main/java/fault/domain/fault/controller/model/request/RejectFaultRequest.java +++ b/fault/src/main/java/fault/domain/fault/controller/model/request/FaultRequest.java @@ -10,7 +10,7 @@ @Data @AllArgsConstructor @NoArgsConstructor -public class RejectFaultRequest { +public class FaultRequest { @NotNull private Long receivingId; diff --git a/fault/src/main/java/fault/domain/fault/controller/model/response/RejectFaultResponse.java b/fault/src/main/java/fault/domain/fault/controller/model/response/FaultResponse.java similarity index 77% rename from fault/src/main/java/fault/domain/fault/controller/model/response/RejectFaultResponse.java rename to fault/src/main/java/fault/domain/fault/controller/model/response/FaultResponse.java index 8139e841..bd3839ac 100644 --- a/fault/src/main/java/fault/domain/fault/controller/model/response/RejectFaultResponse.java +++ b/fault/src/main/java/fault/domain/fault/controller/model/response/FaultResponse.java @@ -10,11 +10,12 @@ @NoArgsConstructor @AllArgsConstructor @Builder -public class RejectFaultResponse { +public class FaultResponse { private Long faultId; - private Long receivingId; private String description; - private LocalDateTime guaranteeAt; + private Boolean approval; + private LocalDateTime registeredAt; + private Long receivingId; } diff --git a/fault/src/main/java/fault/domain/fault/converter/FaultConverter.java b/fault/src/main/java/fault/domain/fault/converter/FaultConverter.java index a5d273fc..3738ab45 100644 --- a/fault/src/main/java/fault/domain/fault/converter/FaultConverter.java +++ b/fault/src/main/java/fault/domain/fault/converter/FaultConverter.java @@ -3,11 +3,11 @@ import db.domain.fault.FaultEntity; import db.domain.image.ImageEntity; import db.domain.imagemapping.ImageMappingEntity; -import fault.domain.fault.controller.model.request.RejectFaultRequest; +import fault.domain.fault.controller.model.request.FaultRequest; import fault.domain.fault.controller.model.response.FaultImageResponse; import fault.domain.fault.controller.model.response.FaultListResponse; import fault.domain.fault.controller.model.response.AddFaultResponse; -import fault.domain.fault.controller.model.response.RejectFaultResponse; +import fault.domain.fault.controller.model.response.FaultResponse; import global.annotation.Converter; import java.time.LocalDateTime; import java.util.List; @@ -17,11 +17,11 @@ @RequiredArgsConstructor public class FaultConverter { - public FaultEntity toEntity(RejectFaultRequest rejectFaultRequest, Long userId) { + public FaultEntity toEntity(FaultRequest faultRequest, Long userId) { return FaultEntity.builder() - .guaranteeAt(LocalDateTime.now()) - .description(rejectFaultRequest.getDescription()) - .receivingId(rejectFaultRequest.getReceivingId()) + .description(faultRequest.getDescription()) + .registeredAt(LocalDateTime.now()) + .receivingId(faultRequest.getReceivingId()) .userId(userId) .build(); } @@ -56,13 +56,15 @@ public FaultImageResponse toResponse(ImageEntity imageEntity) { .build(); } - public RejectFaultResponse toResponse(FaultEntity faultEntity) { - return RejectFaultResponse.builder() + public FaultResponse toResponse(FaultEntity faultEntity) { + return FaultResponse.builder() .faultId(faultEntity.getId()) + .approval(faultEntity.getApproval()) .receivingId(faultEntity.getReceivingId()) .description(faultEntity.getDescription()) - .guaranteeAt(faultEntity.getGuaranteeAt()) + .registeredAt(faultEntity.getRegisteredAt()) .build(); } + } diff --git a/fault/src/main/java/fault/domain/fault/converter/MessageConverter.java b/fault/src/main/java/fault/domain/fault/converter/MessageConverter.java deleted file mode 100644 index 7cc61cc2..00000000 --- a/fault/src/main/java/fault/domain/fault/converter/MessageConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package fault.domain.fault.converter; - -import fault.domain.fault.controller.model.common.MessageResponse; -import global.annotation.Converter; - -@Converter -public class MessageConverter { - public MessageResponse toMassageResponse(String message) { - return MessageResponse.builder() - .Message(message) - .build(); - } -} diff --git a/fault/src/main/java/fault/domain/fault/service/FaultService.java b/fault/src/main/java/fault/domain/fault/service/FaultService.java index 00516f15..572b30f7 100644 --- a/fault/src/main/java/fault/domain/fault/service/FaultService.java +++ b/fault/src/main/java/fault/domain/fault/service/FaultService.java @@ -2,6 +2,9 @@ import db.domain.fault.FaultEntity; import db.domain.fault.FaultRepository; +import fault.common.error.FaultErrorCode; +import fault.common.exception.fault.ExistsFaultRequestException; +import fault.domain.fault.controller.model.request.FaultRequest; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,8 +14,15 @@ public class FaultService { private final FaultRepository faultRepository; - - public FaultEntity rejectFault(FaultEntity faultEntity) { + public FaultEntity approvalFault(FaultEntity faultEntity, Boolean approval) { + faultEntity.setApproval(approval); return faultRepository.save(faultEntity); } + + public void checkFaultRequest(Long receivingId) { + boolean exists = faultRepository.existsByReceivingId(receivingId); + if(exists) { + throw new ExistsFaultRequestException(FaultErrorCode.EXISTS_FAULT_REQUEST); + } + } } diff --git a/fault/src/main/java/fault/domain/receiving/service/ReceivingService.java b/fault/src/main/java/fault/domain/receiving/service/ReceivingService.java index 0357fd7a..cfb35fc5 100644 --- a/fault/src/main/java/fault/domain/receiving/service/ReceivingService.java +++ b/fault/src/main/java/fault/domain/receiving/service/ReceivingService.java @@ -19,7 +19,7 @@ public ReceivingEntity getReceivingBy(Long receivingId) { .orElseThrow((() -> new ReceivingNotFoundException(ErrorCode.NULL_POINT))); } - public void approveFault(Long receivingId) { + public void setReceivingStatusBy(Long receivingId, ReceivingStatus status) { ReceivingEntity receivingEntity = this.getReceivingBy(receivingId); receivingEntity.setStatus(ReceivingStatus.DELIVERY); receivingRepository.save(receivingEntity); diff --git a/settings.gradle b/settings.gradle index 2f2f5210..dafcb726 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,4 +7,5 @@ include 'gateway' include 'users' include 'image' include 'fault' +include 'store' diff --git a/store/build.gradle b/store/build.gradle new file mode 100644 index 00000000..c0ef2ad2 --- /dev/null +++ b/store/build.gradle @@ -0,0 +1,59 @@ +plugins { + id 'java' + id 'org.springframework.boot' + id 'io.spring.dependency-management' +} + +group = 'org.fx' +version = '1.0-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + //implementation 'org.springframework.boot:spring-boot-starter-security' + + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.3.3' + + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + + implementation 'io.jsonwebtoken:jjwt-api:0.11.5' + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' + + // QueryDsl + implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' + annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" + + implementation 'org.springframework.boot:spring-boot-starter-validation' + + implementation project(":db") + implementation project(":global") +} + +test { + useJUnitPlatform() +} + +bootJar { + enabled = true +} + +jar { + enabled = false +} \ No newline at end of file diff --git a/store/src/main/java/store/StoreApplication.java b/store/src/main/java/store/StoreApplication.java new file mode 100644 index 00000000..f969a1cf --- /dev/null +++ b/store/src/main/java/store/StoreApplication.java @@ -0,0 +1,12 @@ +package store; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class StoreApplication { + + public static void main(String[] args) { + SpringApplication.run(StoreApplication.class, args); + } +} diff --git a/store/src/main/java/store/common/config/jpa/JpaConfig.java b/store/src/main/java/store/common/config/jpa/JpaConfig.java new file mode 100644 index 00000000..5d865768 --- /dev/null +++ b/store/src/main/java/store/common/config/jpa/JpaConfig.java @@ -0,0 +1,12 @@ +package store.common.config.jpa; + +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@Configuration +@EntityScan(basePackages = {"db"}) +@EnableJpaRepositories(basePackages = {"db"}) +public class JpaConfig { + +} diff --git a/store/src/main/java/store/domain/business/StoreBusiness.java b/store/src/main/java/store/domain/business/StoreBusiness.java new file mode 100644 index 00000000..5a1911ec --- /dev/null +++ b/store/src/main/java/store/domain/business/StoreBusiness.java @@ -0,0 +1,82 @@ +package store.domain.business; + +import db.domain.goods.GoodsEntity; +import db.domain.goods.enums.GoodsStatus; +import db.domain.receiving.ReceivingEntity; +import db.domain.receiving.enums.ReceivingStatus; +import db.domain.shipping.ShippingEntity; +import db.domain.shipping.enums.ShippingStatus; +import global.annotation.Business; +import java.util.List; +import lombok.RequiredArgsConstructor; +import store.domain.controller.model.GoodsResponse; +import store.domain.controller.model.ReceivingResponse; +import store.domain.controller.model.ShippingResponse; +import store.domain.converter.GoodsConverter; +import store.domain.converter.ReceivingConverter; +import store.domain.converter.ShippingConverter; +import store.domain.service.GoodsService; +import store.domain.service.ImageService; +import store.domain.service.ReceivingService; +import store.domain.service.ShippingService; + +@Business +@RequiredArgsConstructor +public class StoreBusiness { + + private final ReceivingService receivingService; + private final ReceivingConverter receivingConverter; + private final ShippingService shippingService; + private final ShippingConverter shippingConverter; + private final GoodsService goodsService; + private final GoodsConverter goodsConverter; + private final ImageService imageService; + + + public List getRequestReceiving(ReceivingStatus status) { + List receivingEntityList = receivingService.getRequestReceivingBy(status); + return receivingEntityList.stream().map(receivingEntity -> { + return receivingConverter.toResponse(receivingEntity); + }).toList(); + } + + public List getRequestReceiving() { + List receivingEntityList = receivingService.getRequestReceiving(); + return receivingEntityList.stream().map(receivingEntity -> { + return receivingConverter.toResponse(receivingEntity); + }).toList(); + } + + public List getRequestShipping(ShippingStatus status) { + List shippingEntityList = shippingService.getRequestShippingBy(status); + return shippingEntityList.stream().map(shippingEntity -> { + return shippingConverter.toResponse(shippingEntity); + }).toList(); + } + + public List getGoodsList(GoodsStatus status) { + List goodsEntityList = goodsService.getGoodsListBy(status); + return goodsEntityList.stream().map(goodsEntity -> { + GoodsResponse response = goodsConverter.toResponse(goodsEntity); + response.setBasicImageUrlList(imageService.getBasicImageUrlListBy(goodsEntity.getId())); + response.setFaultImageUrlList(imageService.getFaultImageUrlListBy(goodsEntity.getId())); + return response; + }).toList(); + } + + public ReceivingResponse getReceivingRequestDetail(Long receivingId) { + ReceivingEntity receivingEntity = receivingService.getRequestReceivingBy(receivingId); + ReceivingResponse response = receivingConverter.toResponse(receivingEntity); + response.setGoodsIdList(goodsService.getGoodsListBy(receivingId).stream().map(goodsEntity -> goodsEntity.getId()).toList()); + return response; + } + + public List getGoodsListBy(List goodsIdList) { + return goodsService.getGoodsListBy(goodsIdList).stream().map(goodsEntity -> { + GoodsResponse response = goodsConverter.toResponse(goodsEntity); + response.setBasicImageUrlList(imageService.getBasicImageUrlListBy(goodsEntity.getId())); + return response; + }).toList(); + + } +} diff --git a/store/src/main/java/store/domain/controller/StoreApiController.java b/store/src/main/java/store/domain/controller/StoreApiController.java new file mode 100644 index 00000000..748f149b --- /dev/null +++ b/store/src/main/java/store/domain/controller/StoreApiController.java @@ -0,0 +1,82 @@ +package store.domain.controller; + +import db.domain.goods.enums.GoodsStatus; +import db.domain.receiving.enums.ReceivingStatus; +import db.domain.shipping.enums.ShippingStatus; +import jakarta.annotation.PostConstruct; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +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.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import store.domain.business.StoreBusiness; +import store.domain.controller.model.GoodsResponse; +import store.domain.controller.model.ReceivingResponse; +import store.domain.controller.model.ShippingResponse; + +@Controller +@RequiredArgsConstructor +@RequestMapping("/api/store") +public class StoreApiController { + + private final StoreBusiness storeBusiness; + + @GetMapping("/receiving") + public String receivingListWhitStatus(@RequestParam(required = false) ReceivingStatus status,Model model){ + if (status == null){ + status = ReceivingStatus.RECEIVING; + } + List response = storeBusiness.getRequestReceiving(status); + model.addAttribute("receivingList" , response); + return "receivingList"; + } + + @GetMapping("/receiving/{receivingId}") + public String showReceiving(@PathVariable Long receivingId,Model model){ + ReceivingResponse response = storeBusiness.getReceivingRequestDetail(receivingId); + List goodsResponses = storeBusiness.getGoodsListBy(response.getGoodsIdList()); + model.addAttribute("receivingRequest" , response); + model.addAttribute("goodsList" , goodsResponses); + return "receivingDetail"; + } + + + @GetMapping("/shipping") + public String shippingList(@RequestParam(required = false) ShippingStatus status, Model model){ + + if (status == null){ + status = ShippingStatus.PENDING; + } + + List response = storeBusiness.getRequestShipping(status); + model.addAttribute("shippingList" , response); + return "shippingList"; + } + + @GetMapping("/goods") + public String goodsList(@RequestParam(required = false)GoodsStatus status,Model model){ + List response = storeBusiness.getGoodsList(status); + model.addAttribute("goodsList" , response); + return "goodsList"; + } + + @ModelAttribute + public ReceivingStatus[] receivingStatus(){ + return ReceivingStatus.values(); + } + + @ModelAttribute + public ShippingStatus[] shippingStatus(){ + return ShippingStatus.values(); + } + + @ModelAttribute + public GoodsStatus[] goodsStatus(){ + return GoodsStatus.values(); + } + +} diff --git a/store/src/main/java/store/domain/controller/model/GoodsResponse.java b/store/src/main/java/store/domain/controller/model/GoodsResponse.java new file mode 100644 index 00000000..dd92803e --- /dev/null +++ b/store/src/main/java/store/domain/controller/model/GoodsResponse.java @@ -0,0 +1,36 @@ +package store.domain.controller.model; + +import db.domain.goods.enums.GoodsCategory; +import db.domain.goods.enums.GoodsStatus; +import java.time.LocalDateTime; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class GoodsResponse { + + private Long id; + + private String name; + + private String modelName; + + private GoodsCategory category; + + private int quantity; + + private LocalDateTime abandonmentAt; + + private GoodsStatus status; + + private List basicImageUrlList; + + private List faultImageUrlList; + +} diff --git a/store/src/main/java/store/domain/controller/model/ReceivingResponse.java b/store/src/main/java/store/domain/controller/model/ReceivingResponse.java new file mode 100644 index 00000000..d8232fb7 --- /dev/null +++ b/store/src/main/java/store/domain/controller/model/ReceivingResponse.java @@ -0,0 +1,20 @@ +package store.domain.controller.model; + +import db.domain.receiving.enums.ReceivingStatus; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class ReceivingResponse { + + private Long id; + private String visitAddress; + private LocalDateTime visitDate; + private LocalDateTime guaranteeAt; + private ReceivingStatus status; + private List goodsIdList; + +} diff --git a/store/src/main/java/store/domain/controller/model/ShippingResponse.java b/store/src/main/java/store/domain/controller/model/ShippingResponse.java new file mode 100644 index 00000000..a79bdd9b --- /dev/null +++ b/store/src/main/java/store/domain/controller/model/ShippingResponse.java @@ -0,0 +1,29 @@ +package store.domain.controller.model; + +import db.domain.receiving.enums.ReceivingStatus; +import db.domain.shipping.enums.ShippingStatus; +import jakarta.persistence.Column; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class ShippingResponse { + + private Long id; + + private LocalDateTime deliveryDate; + + private String deliveryAddress; + + private ShippingStatus status; + + private Long userId; + + private Long deliveryMan; + +} diff --git a/store/src/main/java/store/domain/converter/GoodsConverter.java b/store/src/main/java/store/domain/converter/GoodsConverter.java new file mode 100644 index 00000000..432fc0e2 --- /dev/null +++ b/store/src/main/java/store/domain/converter/GoodsConverter.java @@ -0,0 +1,22 @@ +package store.domain.converter; + +import db.domain.goods.GoodsEntity; +import global.annotation.Converter; +import store.domain.controller.model.GoodsResponse; + +@Converter +public class GoodsConverter { + + public GoodsResponse toResponse(GoodsEntity goodsEntity) { + return GoodsResponse.builder() + .id(goodsEntity.getId()) + .name(goodsEntity.getName()) + .modelName(goodsEntity.getModelName()) + .category(goodsEntity.getCategory()) + .quantity(goodsEntity.getQuantity()) + .abandonmentAt(goodsEntity.getAbandonmentAt()) + .status(goodsEntity.getStatus()) + .build(); + } + +} diff --git a/store/src/main/java/store/domain/converter/ReceivingConverter.java b/store/src/main/java/store/domain/converter/ReceivingConverter.java new file mode 100644 index 00000000..35be7928 --- /dev/null +++ b/store/src/main/java/store/domain/converter/ReceivingConverter.java @@ -0,0 +1,20 @@ +package store.domain.converter; + +import db.domain.receiving.ReceivingEntity; +import global.annotation.Converter; +import store.domain.controller.model.ReceivingResponse; + +@Converter +public class ReceivingConverter { + + + public ReceivingResponse toResponse(ReceivingEntity receivingEntity) { + return ReceivingResponse.builder() + .id(receivingEntity.getId()) + .visitAddress(receivingEntity.getVisitAddress()) + .visitDate(receivingEntity.getVisitDate()) + .status(receivingEntity.getStatus()) + .guaranteeAt(receivingEntity.getGuaranteeAt()) + .build(); + } +} diff --git a/store/src/main/java/store/domain/converter/ShippingConverter.java b/store/src/main/java/store/domain/converter/ShippingConverter.java new file mode 100644 index 00000000..479b1b93 --- /dev/null +++ b/store/src/main/java/store/domain/converter/ShippingConverter.java @@ -0,0 +1,23 @@ +package store.domain.converter; + +import db.domain.receiving.ReceivingEntity; +import db.domain.shipping.ShippingEntity; +import global.annotation.Converter; +import store.domain.controller.model.ReceivingResponse; +import store.domain.controller.model.ShippingResponse; + +@Converter +public class ShippingConverter { + + + public ShippingResponse toResponse(ShippingEntity shippingEntity) { + return ShippingResponse.builder() + .id(shippingEntity.getId()) + .deliveryAddress(shippingEntity.getDeliveryAddress()) + .status(shippingEntity.getStatus()) + .deliveryDate(shippingEntity.getDeliveryDate()) + .userId(shippingEntity.getUserId()) + .deliveryMan(shippingEntity.getDeliveryMan()) + .build(); + } +} diff --git a/store/src/main/java/store/domain/service/GoodsService.java b/store/src/main/java/store/domain/service/GoodsService.java new file mode 100644 index 00000000..1ac096d1 --- /dev/null +++ b/store/src/main/java/store/domain/service/GoodsService.java @@ -0,0 +1,29 @@ +package store.domain.service; + +import db.domain.goods.GoodsEntity; +import db.domain.goods.GoodsRepository; +import db.domain.goods.enums.GoodsStatus; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class GoodsService { + + private final GoodsRepository goodsRepository; + + public List getGoodsListBy(GoodsStatus status) { + return goodsRepository.findAllByStatusOrderByIdDesc(status); + } + + public List getGoodsListBy(Long receivingId) { + return goodsRepository.findAllByReceivingIdOrderByIdDesc(receivingId); + } + + // TODO Exception 처리 필요 + public List getGoodsListBy(List goodsIdList) { + return goodsIdList.stream().map(goodsId -> goodsRepository.findById(goodsId).orElseThrow(()-> new RuntimeException("해당 상품이 존재하지 않습니다."))).toList(); + } + +} diff --git a/store/src/main/java/store/domain/service/ImageService.java b/store/src/main/java/store/domain/service/ImageService.java new file mode 100644 index 00000000..6476ac3f --- /dev/null +++ b/store/src/main/java/store/domain/service/ImageService.java @@ -0,0 +1,37 @@ +package store.domain.service; + +import db.domain.image.ImageEntity; +import db.domain.image.ImageRepository; +import db.domain.image.enums.ImageKind; +import db.domain.imagemapping.ImageMappingEntity; +import db.domain.imagemapping.ImageMappingRepository; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ImageService { + + private final ImageRepository imageRepository; + private final ImageMappingRepository imageMappingRepository; + + public List getBasicImageUrlListBy(Long id) { + return getImageUrlList(id,ImageKind.BASIC); + } + + public List getFaultImageUrlListBy(Long id) { + return getImageUrlList(id,ImageKind.FAULT); + } + + private List getImageUrlList(Long id,ImageKind kind) { + return imageMappingRepository.findAllByGoodsIdAndKindOrderByIdDesc(id, kind) + .stream().map(imageMappingEntity -> { + ImageEntity imageEntity = imageRepository.findFirstByImageMappingIdOrderByIdDesc( + imageMappingEntity.getId()) + .orElseThrow(() -> new RuntimeException("존재하지 않는 이미지 입니다.")); + return imageEntity.getImageUrl(); + }).toList(); + } + +} diff --git a/store/src/main/java/store/domain/service/ReceivingService.java b/store/src/main/java/store/domain/service/ReceivingService.java new file mode 100644 index 00000000..f97172b8 --- /dev/null +++ b/store/src/main/java/store/domain/service/ReceivingService.java @@ -0,0 +1,28 @@ +package store.domain.service; + +import db.domain.receiving.ReceivingEntity; +import db.domain.receiving.ReceivingRepository; +import db.domain.receiving.enums.ReceivingStatus; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReceivingService { + + private final ReceivingRepository receivingRepository; + + public List getRequestReceivingBy(ReceivingStatus status) { + return receivingRepository.findAllByStatusOrderByVisitDate(status); + } + + public List getRequestReceiving() { + return receivingRepository.findAll(); + } + + // TODO Exception 처리 필요 + public ReceivingEntity getRequestReceivingBy(Long receivingId) { + return receivingRepository.findFirstById(receivingId).orElseThrow(() -> new RuntimeException("존재하지 않는 요청서입니다.")); + } +} diff --git a/store/src/main/java/store/domain/service/ShippingService.java b/store/src/main/java/store/domain/service/ShippingService.java new file mode 100644 index 00000000..344c0bb7 --- /dev/null +++ b/store/src/main/java/store/domain/service/ShippingService.java @@ -0,0 +1,22 @@ +package store.domain.service; + +import db.domain.receiving.ReceivingEntity; +import db.domain.receiving.ReceivingRepository; +import db.domain.receiving.enums.ReceivingStatus; +import db.domain.shipping.ShippingEntity; +import db.domain.shipping.ShippingRepository; +import db.domain.shipping.enums.ShippingStatus; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ShippingService { + + private final ShippingRepository shippingRepository; + + public List getRequestShippingBy(ShippingStatus status) { + return shippingRepository.findAllByStatusOrderByDeliveryDate(status); + } +} diff --git a/store/src/main/resources/application.yml b/store/src/main/resources/application.yml new file mode 100644 index 00000000..2f0c32c4 --- /dev/null +++ b/store/src/main/resources/application.yml @@ -0,0 +1,25 @@ +spring: + jpa: + show-sql: true + hibernate: + ddl-auto: create + properties: + hibernate: + format_sql: true + dialect: org.hibernate.dialect.MySQL8Dialect + datasource: + url: jdbc:mysql://localhost:3306/baobab?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: 1234 + +jwt: + secret: + key: shinyangjunglee_baobab_passwordkey + access-token: + plus-hour: 1 + refresh-token: + plus-hour: 12 + +server: + port: 8085 \ No newline at end of file diff --git a/store/src/main/resources/templates/addFault.html b/store/src/main/resources/templates/addFault.html new file mode 100644 index 00000000..424518c6 --- /dev/null +++ b/store/src/main/resources/templates/addFault.html @@ -0,0 +1,97 @@ + + + + + + 결함 등록 + + + + + +
+ + +
+
+ + BAOBAB + + + + +
+ +
+
+
+ +
+
+
물품 A
+
Model Name
+

물품 ID : 1

+

상태 : 입고 진행 중

+

카테고리 : 소형 가전

+

수량 : 1

+ +
+
+
+
+ + +
+ + +
+
+
+
+
+ +
+
+ +
+
+ +
+ +
+
+ + +
+ + + + + \ No newline at end of file diff --git a/store/src/main/resources/templates/goodsList.html b/store/src/main/resources/templates/goodsList.html new file mode 100644 index 00000000..edc7d418 --- /dev/null +++ b/store/src/main/resources/templates/goodsList.html @@ -0,0 +1,72 @@ + + + + + + 물품 요청서 목록 조회 + + + + + +
+ + +
+
+ + BAOBAB + + + + +
+ +
+
+
+ + + + +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + +
ID상품명모델명카테고리수량
1소형가구소형가구소형가구소형가구
+ +
+ + + + \ No newline at end of file diff --git a/store/src/main/resources/templates/receivingDetail.html b/store/src/main/resources/templates/receivingDetail.html new file mode 100644 index 00000000..5344bcbd --- /dev/null +++ b/store/src/main/resources/templates/receivingDetail.html @@ -0,0 +1,174 @@ + + + + + + 요청서 상세 조회 + + + + + +
+ + +
+
+ + BAOBAB + + + + +
+ +
+
+
+ + + + +
+
+

+ +

+
+
+
+
+
요청서 ID
+
요청서 + 상태
+

주소 :

+

+ 방문 일자 :

+

+ 결함 인정일:

+
+
+
+
+
+
+

+ +

+
+
+
+
+
물품 A
+
Model Name
+

물품 ID : 1

+

상태 : 입고 진행 중

+

카테고리 : 대형 가전 +

+

수량 : 1

+ + + + + + +
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+ + + + + + +
+ + + + + \ No newline at end of file diff --git a/store/src/main/resources/templates/receivingList.html b/store/src/main/resources/templates/receivingList.html new file mode 100644 index 00000000..71a13c82 --- /dev/null +++ b/store/src/main/resources/templates/receivingList.html @@ -0,0 +1,72 @@ + + + + + + 입고 요청서 목록 조회 + + + + + +
+ + +
+
+ + BAOBAB + + + + +
+ +
+
+
+ + + + +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
ID카테고리방문 주소방문 날짜
1소형가구소형가구소형가구
+ + + +
+ + + + \ No newline at end of file diff --git a/store/src/main/resources/templates/shippingList.html b/store/src/main/resources/templates/shippingList.html new file mode 100644 index 00000000..439c6d0a --- /dev/null +++ b/store/src/main/resources/templates/shippingList.html @@ -0,0 +1,72 @@ + + + + + + 출고 요청서 목록 조회 + + + + + +
+ + +
+
+ + BAOBAB + + + + +
+ +
+
+
+ + + +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
ID상태방문 주소방문 날짜
1소형가구소형가구소형가구
+ + + +
+ + + + + \ No newline at end of file diff --git a/users/src/main/java/users/business/UsersBusiness.java b/users/src/main/java/users/business/UsersBusiness.java index 2e0f5cc9..7c517cf0 100644 --- a/users/src/main/java/users/business/UsersBusiness.java +++ b/users/src/main/java/users/business/UsersBusiness.java @@ -69,6 +69,11 @@ public UserResponse getUserInformation(String email) { return usersConverter.toResponse(userEntity); } + public UserResponse getUserInformation(Long userId) { + UserEntity userEntity = usersService.getUserByUserIdWithThrow(userId); + return usersConverter.toResponse(userEntity); + } + public MessageResponse unregister(String email) { usersService.unregister(email); return MessageResponse.builder() diff --git a/users/src/main/java/users/controller/UsersOpenApiController.java b/users/src/main/java/users/controller/UsersOpenApiController.java index 2fa75010..0bc8c62f 100644 --- a/users/src/main/java/users/controller/UsersOpenApiController.java +++ b/users/src/main/java/users/controller/UsersOpenApiController.java @@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.validation.Errors; +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.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -14,6 +16,7 @@ import users.controller.model.duplicaiton.DuplicationNameRequest; import users.controller.model.duplicaiton.DuplicationResponse; import users.controller.model.login.UserLoginRequest; +import users.controller.model.login.UserResponse; import users.controller.model.register.UsersRegisterRequest; import users.controller.model.register.UsersRegisteredResponse; import users.security.jwt.model.TokenResponse; @@ -62,6 +65,11 @@ public Api duplicationNameCheck( return Api.OK(response); } - + @GetMapping("/{userId}") + @Operation(summary = "[사용자 고유 아이디로 사용자 정보 조회]") + public Api getUserInfo(@PathVariable Long userId){ + UserResponse response = usersBusiness.getUserInformation(userId); + return Api.OK(response); + } } diff --git a/users/src/main/java/users/service/UsersService.java b/users/src/main/java/users/service/UsersService.java index c56fa823..edde2cf5 100644 --- a/users/src/main/java/users/service/UsersService.java +++ b/users/src/main/java/users/service/UsersService.java @@ -97,4 +97,8 @@ public void unregister(String email) { } } + + public UserEntity getUserByUserIdWithThrow(Long userId) { + return usersRepository.findFirstByIdAndStatusOrderByIdDesc(userId,UserStatus.REGISTERED).orElseThrow(() -> new UserNotFoundException(UserErrorCode.USER_NOT_FOUND)); + } } \ No newline at end of file diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/business/UsedGoodsOrderBusiness.java b/warehouse/src/main/java/warehouse/domain/usedgoods/business/UsedGoodsOrderBusiness.java index 2c0892bb..def4623b 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/business/UsedGoodsOrderBusiness.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/business/UsedGoodsOrderBusiness.java @@ -1,19 +1,27 @@ package warehouse.domain.usedgoods.business; +import db.domain.goods.GoodsEntity; +import db.domain.goods.enums.GoodsStatus; import db.domain.usedgoods.UsedGoodsEntity; import db.domain.usedgoods.enums.UsedGoodsStatus; import db.domain.usedgoodsorder.UsedGoodsOrderEntity; -import db.domain.usedgoodsorder.enums.UsedGoodsOrderStatus; import global.annotation.Business; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import warehouse.common.error.UsedGoodsErrorCode; -import warehouse.common.exception.usedGoods.ApprovedOrderException; import warehouse.common.exception.usedGoods.ExistingOrderException; import warehouse.common.exception.usedGoods.InvalidOrderAuthorityException; +import warehouse.domain.goods.controller.model.GoodsResponse; +import warehouse.domain.goods.converter.GoodsConverter; +import warehouse.domain.goods.service.GoodsService; +import warehouse.domain.image.controller.model.ImageListResponse; +import warehouse.domain.image.converter.ImageConverter; import warehouse.domain.usedgoods.controller.model.response.UsedGoodsOrderResponse; -import warehouse.domain.usedgoods.controller.model.response.UsedGoodsStatusResponse; +import warehouse.domain.usedgoods.controller.model.response.UsedGoodsSearchResponse; +import warehouse.domain.usedgoods.converter.UsedGoodsConverter; import warehouse.domain.usedgoods.converter.UsedGoodsOrderConverter; import warehouse.domain.usedgoods.service.UsedGoodsOrderService; import warehouse.domain.usedgoods.service.UsedGoodsService; @@ -29,38 +37,64 @@ public class UsedGoodsOrderBusiness { private final UsedGoodsOrderService usedGoodsOrderService; private final UsedGoodsService usedGoodsService; private final UsedGoodsOrderConverter usedGoodsOrderConverter; + private final GoodsService goodsService; + private final ImageConverter imageConverter; + private final GoodsConverter goodsConverter; + private final UsedGoodsConverter usedGoodsConverter; - public UsedGoodsOrderResponse requestOrder(Long usedGoodsId, String email) { + public UsedGoodsOrderResponse orderUsedGoods(Long usedGoodsId, String email) { // 1. 구매자의 userId - Long userId = getUserId(email); + Long buyerId = getUserId(email); // 2. UsedGoods 조회 UsedGoodsEntity usedGoodsEntity = usedGoodsService.getUsedGoodsBy(usedGoodsId); // 3. 자신이 올린 물품을 구매하려는 경우 방지 - if (usedGoodsEntity.getUserId().equals(userId)) { + if (usedGoodsEntity.getUserId().equals(buyerId)) { throw new InvalidOrderAuthorityException(UsedGoodsErrorCode.INVALID_ORDER_AUTHORITY); } // 4. 구매자가 이미 거래 요청을 했는지 확인 - if (usedGoodsOrderService.hasExistingOrder(usedGoodsId, userId)) { + if (usedGoodsOrderService.hasExistingOrder(usedGoodsId, buyerId)) { throw new ExistingOrderException(UsedGoodsErrorCode.EXISTING_ORDER); } UsedGoodsOrderEntity orderEntity = usedGoodsOrderConverter.toEntity(usedGoodsEntity, - userId); + buyerId); + + // 5. 새로운 구매 요청서 생성 + UsedGoodsOrderEntity savedOrderEntity = usedGoodsOrderService.orderUsedGoods(orderEntity); + + // 6. UsedGoodsStatus = SOLD 로 변경 + setUsedGoodsStatusBy(usedGoodsEntity, UsedGoodsStatus.SOLD); - // 5. 새로운 요청서 생성, status = REQUESTED - UsedGoodsOrderEntity savedOrderEntity = usedGoodsOrderService.requestOrder(orderEntity); + // 7. GoodsStatus = STORAGE 로 변경 + GoodsEntity goodsEntity = goodsService.getGoodsBy(usedGoodsEntity.getGoodsId()); + setGoodsStatusBy(goodsEntity.getId(), GoodsStatus.STORAGE); - // 6, UsedGoodsStatus = DEALING (거래중) 으로 변경 - setUsedGoodsStatusBy(usedGoodsEntity, UsedGoodsStatus.DEALING); + // 8. 물품 소유권을 구매자로 변경 + goodsService.setUserId(goodsEntity, buyerId); return usedGoodsOrderConverter.toResponse(savedOrderEntity); } + + public List getSellerOrderRequest(String email) { + Long userId = getUserId(email); + List usedGoodsOrderList = usedGoodsOrderService.getUsedGoodsOrderListBySellerId( + userId); + return usedGoodsOrderConverter.toResponse(usedGoodsOrderList); + } + + public List getBuyerOrderRequest(String email) { + Long userId = getUserId(email); + List usedGoodsOrderList = usedGoodsOrderService.getUsedGoodsOrderListByBuyerId( + userId); + return usedGoodsOrderConverter.toResponse(usedGoodsOrderList); + } + /** * 판매자는 구매 요청 내역을 조회할 수 있다. */ @@ -81,136 +115,60 @@ public List getOrderList(Long usedGoodsId, String email) return usedGoodsOrderConverter.toResponse(orderEntityList); } - public UsedGoodsStatusResponse approveOrder(Long usedGoodsOrderId, String email) { - - Long userId = getUserId(email); - - UsedGoodsOrderEntity orderEntity = getUsedGoodsOrderBy(usedGoodsOrderId); - - // 1. usedGoodsId 로 판매자 ID 조회 - UsedGoodsEntity entity = usedGoodsService.getUsedGoodsBy(orderEntity.getUsedGoodsId()); - - // 2. 판매자 권한 확인 - validateSellerAuthority(entity, userId); - - // 3. 요청서 목록 조회 - List orderList = usedGoodsOrderService.getUsedGoodsOrderListBy( - orderEntity.getUsedGoodsId()); - - // 4. 요청서 목록 중 APPROVED 가 있는 경우 예외 -> 2중 승인 방지 - validateApprovedOrder(orderList); - - // 5. UsedGoodsOrderStatus = APPROVED 로 업데이트 (거래 승인) - usedGoodsOrderService.setUsedGoodsOrderStatusBy(orderEntity, UsedGoodsOrderStatus.APPROVED); - - // 6. 나머지 요청서를 HOLD 로 - orderList.stream() - .filter(order -> !order.getStatus().equals(UsedGoodsOrderStatus.APPROVED)) - .forEach(order -> usedGoodsOrderService.setUsedGoodsOrderStatusBy(order, - UsedGoodsOrderStatus.HOLD)); - - // 7. UsedGoodsStatus = DEALING 조회 업데이트 - UsedGoodsEntity usedGoodsEntity = usedGoodsService.getUsedGoodsBy( - orderEntity.getUsedGoodsId(), UsedGoodsStatus.DEALING); - - // 8. UsedGoodsStatus = DEAL 업데이트 - setUsedGoodsStatusBy(usedGoodsEntity, UsedGoodsStatus.DEAL); - return usedGoodsOrderConverter.toResponse(UsedGoodsStatus.DEAL); + private static void validateSellerAuthority(UsedGoodsEntity usedGoodsEntity, Long userId) { + if (!usedGoodsEntity.getUserId().equals(userId)) { + throw new InvalidOrderAuthorityException(UsedGoodsErrorCode.INVALID_ORDER_AUTHORITY); + } } - public UsedGoodsStatusResponse transferOrder(Long usedGoodsOrderId, String email) { - - Long userId = getUserId(email); - - // 1. 거래 요청서 조회 - UsedGoodsOrderEntity orderEntity = getUsedGoodsOrderBy(usedGoodsOrderId); - - // 2. 자신의 요청서인지 검증 - validateOrderAuthority(orderEntity, userId); - - // 3. UsedGoodsStatus = DEAL (중고 거래 확정) 조회 - UsedGoodsEntity usedGoodsEntity = usedGoodsService.getUsedGoodsBy( - orderEntity.getUsedGoodsId(), UsedGoodsStatus.DEAL); - - // 4. 송금 시 UsedGoodsStatus = REMITTANCE (송금 확인) 으로 변경 - setUsedGoodsStatusBy(usedGoodsEntity, UsedGoodsStatus.REMITTANCE); - - return usedGoodsOrderConverter.toResponse(UsedGoodsStatus.REMITTANCE); + private Long getUserId(String email) { + return usersService.getUserWithThrow(email).getId(); } - public UsedGoodsStatusResponse receiveUsedGoods(Long usedGoodsOrderId, String email) { - - Long userId = getUserId(email); - - // 1. 거래 요청서 조회 - UsedGoodsOrderEntity orderEntity = getUsedGoodsOrderBy(usedGoodsOrderId); - - // 2. 자신의 요청서인지 검증 - validateOrderAuthority(orderEntity, userId); - - // 3. UsedGoodsStatus = REMITTANCE (송금 확인) 조회 - UsedGoodsEntity usedGoodsEntity = usedGoodsService.getUsedGoodsBy( - orderEntity.getUsedGoodsId(), UsedGoodsStatus.REMITTANCE); - - // 4. UsedGoodsStatus = ASSIGNMENT (물건 확인) 으로 변경 - setUsedGoodsStatusBy(usedGoodsEntity, UsedGoodsStatus.ASSIGNMENT); - - return usedGoodsOrderConverter.toResponse(UsedGoodsStatus.ASSIGNMENT); + private void setUsedGoodsStatusBy(UsedGoodsEntity usedGoodsEntity, UsedGoodsStatus status) { + usedGoodsService.setUsedGoodsStatusBy(usedGoodsEntity, status); } - public UsedGoodsStatusResponse completeOrder(Long usedGoodsOrderId, String email) { - - Long userId = getUserId(email); - - // 1. 거래 요청서 조회 - UsedGoodsOrderEntity orderEntity = getUsedGoodsOrderBy(usedGoodsOrderId); - - // 2. UsedGoodsStatus = ASSIGNMENT (물건 확인) 조회 - UsedGoodsEntity usedGoodsEntity = usedGoodsService.getUsedGoodsBy( - orderEntity.getUsedGoodsId(), UsedGoodsStatus.ASSIGNMENT); - - // 3. 권한 확인 - validateSellerAuthority(usedGoodsEntity, userId); + private void setGoodsStatusBy(Long goodsId, GoodsStatus status) { + goodsService.setGoodsStatusBy(goodsId, status); + } - // 4. UsedGoodsStatus = SOLD (판매) 으로 변경 - setUsedGoodsStatusBy(usedGoodsEntity, UsedGoodsStatus.SOLD); - return usedGoodsOrderConverter.toResponse(UsedGoodsStatus.SOLD); - } + public List getPurchasedGoodsList(String email) { + Long userId = usersService.getUserWithThrow(email).getId(); - private static void validateApprovedOrder(List orderList) { - orderList.stream() - .filter(orderEntity -> orderEntity.getStatus().equals(UsedGoodsOrderStatus.APPROVED)) - .findFirst() - .ifPresent(approvedOrder -> { - throw new ApprovedOrderException(UsedGoodsErrorCode.APPROVED_ORDER); - }); - } + List usedGoodsIdList = usedGoodsOrderService.getUsedGoodsOrderListByBuyerId(userId) + .stream() + .map(usedGoodsOrderEntity -> + usedGoodsOrderEntity.getUsedGoodsId() + ).toList(); - private static void validateOrderAuthority(UsedGoodsOrderEntity orderEntity, Long userId) { - if (!orderEntity.getUserId().equals(userId)) { - throw new InvalidOrderAuthorityException(UsedGoodsErrorCode.INVALID_ORDER_AUTHORITY); - } - } + List usedGoodsEntityList = usedGoodsService.getUsedGoodsListBy( + usedGoodsIdList, UsedGoodsStatus.SOLD); - private static void validateSellerAuthority(UsedGoodsEntity usedGoodsEntity, Long userId) { - if (!usedGoodsEntity.getUserId().equals(userId)) { - throw new InvalidOrderAuthorityException(UsedGoodsErrorCode.INVALID_ORDER_AUTHORITY); - } - } + Map goodsEntityMap = getGoodsEntityMap(usedGoodsEntityList); - private UsedGoodsOrderEntity getUsedGoodsOrderBy(Long usedGoodsOrderId) { - return usedGoodsOrderService.getUsedGoodsOrderBy(usedGoodsOrderId); - } + return usedGoodsEntityList.stream().map(usedGoodsEntity -> { + Long goodsId = usedGoodsEntity.getGoodsId(); + GoodsEntity goodsEntity = goodsEntityMap.get(goodsId); + ImageListResponse imageListResponse = imageConverter.toImageListResponse(goodsEntity); + GoodsResponse response = goodsConverter.toResponse(goodsEntity, imageListResponse); + return usedGoodsConverter.toSearchResponse(usedGoodsEntity, response); + }).toList(); - private Long getUserId(String email) { - return usersService.getUserWithThrow(email).getId(); } - private void setUsedGoodsStatusBy(UsedGoodsEntity usedGoodsEntity, UsedGoodsStatus status) { - usedGoodsService.setUsedGoodsStatusBy(usedGoodsEntity, status); + private Map getGoodsEntityMap(List usedGoodsEntityList) { + List goodsIdList = usedGoodsEntityList.stream() + .map(usedGoodsEntity -> usedGoodsEntity.getGoodsId()).toList(); + List goodsEntityList = goodsService.getGoodsListBy(goodsIdList); + Map goodsEntityMap = goodsEntityList.stream().collect(Collectors.toMap( + goodsEntity -> goodsEntity.getId(), // key + goodsEntity -> goodsEntity // value + )); + return goodsEntityMap; } } \ No newline at end of file diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsApiController.java b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsApiController.java index ae5ce44c..20ecc60a 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsApiController.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsApiController.java @@ -56,13 +56,6 @@ public Api cancelUsedGoodsList( return Api.OK(response); } - @GetMapping("/{usedGoodsId}") // usedGoodsId 로 중고 상세 조회 - @Operation(summary = "[중고 아이디로 상세 조회]") - public Api getUsedGoodsDetail(@PathVariable Long usedGoodsId) { - UsedGoodsDetailResponse response = usedGoodsBusiness.getUsedGoodsDetail(usedGoodsId); - return Api.OK(response); - } - @GetMapping() @Operation(summary = "[자신이 등록한 중고 물품 검색]", description = "무한 스크롤 방식") public Api> usedGoodsSearchBy( diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOpenApiController.java b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOpenApiController.java index dc3111ed..95c9dc16 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOpenApiController.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOpenApiController.java @@ -9,10 +9,12 @@ import org.springframework.data.web.PageableDefault; 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.RequestMapping; import org.springframework.web.bind.annotation.RestController; import warehouse.domain.usedgoods.business.UsedGoodsBusiness; import warehouse.domain.usedgoods.controller.model.request.SearchCondition; +import warehouse.domain.usedgoods.controller.model.response.UsedGoodsDetailResponse; import warehouse.domain.usedgoods.controller.model.response.UsedGoodsSearchResponse; @RestController @@ -33,4 +35,11 @@ public Api> usedGoodsSearchBy( return Api.OK(response); } + @GetMapping("/{usedGoodsId}") // usedGoodsId 로 중고 상세 조회 + @Operation(summary = "[중고 아이디로 상세 조회]") + public Api getUsedGoodsDetail(@PathVariable Long usedGoodsId) { + UsedGoodsDetailResponse response = usedGoodsBusiness.getUsedGoodsDetail(usedGoodsId); + return Api.OK(response); + } + } diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOrderApiController.java b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOrderApiController.java index 4f1d9364..4403443c 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOrderApiController.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/UsedGoodsOrderApiController.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.Operation; import java.util.List; import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.userdetails.User; import org.springframework.web.bind.annotation.GetMapping; @@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController; import warehouse.domain.usedgoods.business.UsedGoodsOrderBusiness; import warehouse.domain.usedgoods.controller.model.response.UsedGoodsOrderResponse; +import warehouse.domain.usedgoods.controller.model.response.UsedGoodsSearchResponse; import warehouse.domain.usedgoods.controller.model.response.UsedGoodsStatusResponse; @RestController @@ -20,58 +23,41 @@ @RequestMapping("/api/order") public class UsedGoodsOrderApiController { + private static final Logger log = LoggerFactory.getLogger(UsedGoodsOrderApiController.class); private final UsedGoodsOrderBusiness usedGoodsOrderBusiness; @PostMapping("/{usedGoodsId}") // usedGoodsId 로 중고 물품 구매 요청 - @Operation(summary = "[물품 구매 요청]", description = "[구매자] usedGoodsId로 중고 물품 구매 요청") + @Operation(summary = "[물품 구매]", description = "[구매자] usedGoodsId로 중고 물품 구매") public Api requestTransaction(@PathVariable Long usedGoodsId, @AuthenticationPrincipal User user) { - UsedGoodsOrderResponse response = usedGoodsOrderBusiness.requestOrder(usedGoodsId, + UsedGoodsOrderResponse response = usedGoodsOrderBusiness.orderUsedGoods(usedGoodsId, user.getUsername()); return Api.OK(response); } - @GetMapping("/{usedGoodsId}") // usedGoodsId 로 거래 요청서 목록 보기 - @Operation(summary = "[물품 거래 요청 목록 조회]", description = "[판매자] 거래 요청 목록 조회") - public Api> getTransactionList(@PathVariable Long usedGoodsId, + @GetMapping("/sell") + @Operation(summary = "[거래 요청서 리스트 확인]", description = "판매자 API") + public Api> getSellerOrderRequest( @AuthenticationPrincipal User user) { - List response = usedGoodsOrderBusiness.getOrderList(usedGoodsId, + List response = usedGoodsOrderBusiness.getSellerOrderRequest( user.getUsername()); return Api.OK(response); } - @PostMapping("/approve/{usedGoodsOrderId}") // usedGoodsOrderId 로 거래 승인 - @Operation(summary = "[물품 거래 승인]", description = "[판매자] 거래 승인") - public Api approveTransaction(@PathVariable Long usedGoodsOrderId, + @GetMapping("/buy") + @Operation(summary = "[거래 요청서 리스트 확인]", description = "구매자 API") + public Api> getBuyerOrderRequest( @AuthenticationPrincipal User user) { - UsedGoodsStatusResponse response = usedGoodsOrderBusiness.approveOrder(usedGoodsOrderId, + List response = usedGoodsOrderBusiness.getBuyerOrderRequest( user.getUsername()); return Api.OK(response); } - @PostMapping("/transfer/{usedGoodsOrderId}") // usedGoodsOrderId 로 송금하기 - @Operation(summary = "[물품 거래 송금]", description = "[구매자] 송금") - public Api transferTransaction(@PathVariable Long usedGoodsOrderId, + @GetMapping() + @Operation(summary = "[자신이 구매한 물품 조회]") + public Api> getPurchasedGoodsList( @AuthenticationPrincipal User user) { - UsedGoodsStatusResponse response = usedGoodsOrderBusiness.transferOrder(usedGoodsOrderId, - user.getUsername()); - return Api.OK(response); - } - - @PostMapping("/receive/{usedGoodsOrderId}") - @Operation(summary = "[물품 확인]", description = "[구매자] 물품 확인") - public Api receiveUsedGoods(@PathVariable Long usedGoodsOrderId, - @AuthenticationPrincipal User user) { - UsedGoodsStatusResponse response = usedGoodsOrderBusiness.receiveUsedGoods(usedGoodsOrderId, - user.getUsername()); - return Api.OK(response); - } - - @PostMapping("/sold/{usedGoodsOrderId}") - @Operation(summary = "[거래 완료]", description = "[구매자] 거래 완료") - public Api completeTransaction(@PathVariable Long usedGoodsOrderId, - @AuthenticationPrincipal User user) { - UsedGoodsStatusResponse response = usedGoodsOrderBusiness.completeOrder(usedGoodsOrderId, + List response = usedGoodsOrderBusiness.getPurchasedGoodsList( user.getUsername()); return Api.OK(response); } diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/request/SearchCondition.java b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/request/SearchCondition.java index 67ffeba0..448f1436 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/request/SearchCondition.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/request/SearchCondition.java @@ -1,5 +1,6 @@ package warehouse.domain.usedgoods.controller.model.request; +import db.domain.usedgoods.enums.UsedGoodsStatus; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; @@ -16,6 +17,8 @@ public class SearchCondition { private String keyword; // 제목으로 찾기 + private UsedGoodsStatus status; + @Builder.Default private int minPrice = 0; // 최소 가격 diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsDetailResponse.java b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsDetailResponse.java index f1e3c6cb..0660667e 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsDetailResponse.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsDetailResponse.java @@ -1,5 +1,6 @@ package warehouse.domain.usedgoods.controller.model.response; +import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; @@ -19,6 +20,7 @@ public class UsedGoodsDetailResponse { private String description; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") private LocalDateTime postedAt; private GoodsResponse goods; diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsOrderResponse.java b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsOrderResponse.java index 8c761373..895b8b8e 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsOrderResponse.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsOrderResponse.java @@ -1,6 +1,6 @@ package warehouse.domain.usedgoods.controller.model.response; -import db.domain.usedgoodsorder.enums.UsedGoodsOrderStatus; +import com.fasterxml.jackson.annotation.JsonFormat; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Builder; @@ -14,9 +14,14 @@ public class UsedGoodsOrderResponse { private Long usedGoodsOrderId; - private Long userId; // 구매자 ID - private UsedGoodsOrderStatus status; + + private Long buyerId; // 구매자 ID + + private Long sellerId; + + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") private LocalDateTime createdAt; + private Long usedGoodsId; } diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsSearchResponse.java b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsSearchResponse.java index ddeef6f4..514d9537 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsSearchResponse.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/controller/model/response/UsedGoodsSearchResponse.java @@ -1,5 +1,6 @@ package warehouse.domain.usedgoods.controller.model.response; +import com.fasterxml.jackson.annotation.JsonFormat; import db.domain.usedgoods.enums.UsedGoodsStatus; import java.time.LocalDateTime; import lombok.AllArgsConstructor; @@ -20,6 +21,7 @@ public class UsedGoodsSearchResponse { private int price; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") private LocalDateTime postedAt; private UsedGoodsStatus status; diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsConverter.java b/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsConverter.java index 364fa5dc..2234cfaf 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsConverter.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsConverter.java @@ -58,6 +58,7 @@ public EntitySearchCondition toEntitySearchCondition(SearchCondition condition, return EntitySearchCondition.builder() .usedGoodsId(condition.getUsedGoodsId()) .keyword(condition.getKeyword()) + .status(condition.getStatus()) .minPrice(condition.getMinPrice()) .maxPrice(condition.getMaxPrice()) .startDate(condition.getStartDate()) diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsOrderConverter.java b/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsOrderConverter.java index c7322d36..999863c2 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsOrderConverter.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/converter/UsedGoodsOrderConverter.java @@ -4,6 +4,7 @@ import db.domain.usedgoods.enums.UsedGoodsStatus; import db.domain.usedgoodsorder.UsedGoodsOrderEntity; import global.annotation.Converter; +import java.time.LocalDateTime; import java.util.List; import warehouse.domain.usedgoods.controller.model.response.UsedGoodsOrderResponse; import warehouse.domain.usedgoods.controller.model.response.UsedGoodsStatusResponse; @@ -13,16 +14,18 @@ public class UsedGoodsOrderConverter { public UsedGoodsOrderEntity toEntity(UsedGoodsEntity usedGoodsEntity, Long userId) { return UsedGoodsOrderEntity.builder() - .userId(userId) + .sellerId(usedGoodsEntity.getUserId()) + .buyerId(userId) .usedGoodsId(usedGoodsEntity.getId()) + .createdAt(LocalDateTime.now()) .build(); } public UsedGoodsOrderResponse toResponse(UsedGoodsOrderEntity orderEntity) { return UsedGoodsOrderResponse.builder() .usedGoodsOrderId(orderEntity.getId()) - .userId(orderEntity.getUserId()) - .status(orderEntity.getStatus()) + .sellerId(orderEntity.getSellerId()) + .buyerId(orderEntity.getBuyerId()) .createdAt(orderEntity.getCreatedAt()) .usedGoodsId(orderEntity.getUsedGoodsId()) .build(); diff --git a/warehouse/src/main/java/warehouse/domain/usedgoods/service/UsedGoodsOrderService.java b/warehouse/src/main/java/warehouse/domain/usedgoods/service/UsedGoodsOrderService.java index bdbe3654..402a2bdd 100644 --- a/warehouse/src/main/java/warehouse/domain/usedgoods/service/UsedGoodsOrderService.java +++ b/warehouse/src/main/java/warehouse/domain/usedgoods/service/UsedGoodsOrderService.java @@ -2,8 +2,6 @@ import db.domain.usedgoodsorder.UsedGoodsOrderEntity; import db.domain.usedgoodsorder.UsedGoodsOrderRepository; -import db.domain.usedgoodsorder.enums.UsedGoodsOrderStatus; -import java.time.LocalDateTime; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,15 +14,30 @@ public class UsedGoodsOrderService { private final UsedGoodsOrderRepository usedGoodsOrderRepository; - public UsedGoodsOrderEntity requestOrder(UsedGoodsOrderEntity orderEntity) { - orderEntity.setStatus(UsedGoodsOrderStatus.REGISTERED); - orderEntity.setCreatedAt(LocalDateTime.now()); + public UsedGoodsOrderEntity orderUsedGoods(UsedGoodsOrderEntity orderEntity) { return usedGoodsOrderRepository.save(orderEntity); } public List getUsedGoodsOrderListBy(Long usedGoodsId) { List orderEntityList = usedGoodsOrderRepository.findAllByUsedGoodsId( usedGoodsId); + return getValidatedOrderList(orderEntityList); + } + + public List getUsedGoodsOrderListByBuyerId(Long userId) { + List orderEntityList = usedGoodsOrderRepository.findAllByBuyerId( + userId); + return getValidatedOrderList(orderEntityList); + } + + public List getUsedGoodsOrderListBySellerId(Long userId) { + List orderEntityList = usedGoodsOrderRepository.findAllBySellerId( + userId); + return getValidatedOrderList(orderEntityList); + } + + private List getValidatedOrderList( + List orderEntityList) { if (orderEntityList.isEmpty()) { throw new UsedGoodsOrderNotFoundException( UsedGoodsErrorCode.USED_GOODS_ORDER_NOT_FOUND); @@ -32,20 +45,9 @@ public List getUsedGoodsOrderListBy(Long usedGoodsId) { return orderEntityList; } - public UsedGoodsOrderEntity getUsedGoodsOrderBy(Long usedGoodsOrderId) { - return usedGoodsOrderRepository.findFirstById(usedGoodsOrderId) - .orElseThrow(() -> new UsedGoodsOrderNotFoundException( - UsedGoodsErrorCode.USED_GOODS_ORDER_NOT_FOUND)); - } - - public void setUsedGoodsOrderStatusBy(UsedGoodsOrderEntity orderEntity, - UsedGoodsOrderStatus status) { - orderEntity.setStatus(status); - usedGoodsOrderRepository.save(orderEntity); - } - - public Boolean hasExistingOrder(Long usedGoodsId, Long userId) { - return usedGoodsOrderRepository.findByUsedGoodsIdAndUserId(usedGoodsId, userId).isPresent(); + public Boolean hasExistingOrder(Long usedGoodsId, Long buyerId) { + return usedGoodsOrderRepository.findByUsedGoodsIdAndBuyerId(usedGoodsId, buyerId) + .isPresent(); } }