Skip to content

Commit

Permalink
Merge branch 'develop' into feature/12
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/site/goldenticket/domain/nego/service/NegoSchedulerService.java
  • Loading branch information
Su-daa committed Jan 26, 2024
2 parents ea37e18 + 407461d commit d8745a8
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ public void changeStatus() {

//판매자에게 타임오버 알림 전송
alertService.createAlert(product.getUserId(),
"구매자가 20분 이내에 결제를 완료하지 않아 거래가 이루어지지 않았습니다.");
"구매자가 20분 이내에 결제를 완료하지 않아 거래가 종료되었습니다.");
//구매자에게 타임오버 알림 전송
alertService.createAlert(nego.getUser().getId(),
"20분이 초과되었습니다. 아직 구매를 원하신다면, 재결제 버튼을 눌러 결제해주세요.");
"상품 결제 시간 20분이 초과되었습니다. 아직 구매를 원하신다면, 재결제 버튼을 눌러 결제를 완료해주세요.");
//해당 상품 찜한 회원들에게 알림 전송
if (product.getProductStatus().equals(ProductStatus.SELLING)) {
alertService.createAlertOfWishProductToSelling(product.getId(),
Expand Down Expand Up @@ -106,19 +106,13 @@ public void changeStatus() {
// 판매자에게 정산 요청 알림 전송
alertService.createAlert(product.getUserId(),
"'" + product.getAccommodationName() + "(" + product.getRoomName()
+ ")'상품 양도가 완료되었습니다. 영업일 1일 이내 등록한 계좌 정보로 정산 금액이 입금됩니다."
+ "원활한 정산 진행을 위해 '마이페이지 - 나의 계좌'정보를 다시 한번 확인해주세요.");

// 판매자에게 계좌 등록 알림 전송
if (user != null && user.getAccountNumber() == null) {
alertService.createAlert(product.getUserId(),
"'" + product.getAccommodationName() + "(" + product.getRoomName()
+ ")'상품에 대한 원활한 정산을 위해 '마이페이지 > 내 계좌'에서 입금받으실 계좌를 등록해주세요.");
}
+ ")'상품 양도가 완료되었습니다. 최대 9영업일 이내에 등록한 계좌 정보로 정산 금액이 입금됩니다."
+ "원활한 정산 진행을 위해 '마이페이지 - 나의 계좌'정보를 다시 한번 확인해주세요.");

//자동 양도완료 관련 시스템 메세지 전송
chatService.createSystemMessageOfCompletedTransferByScheduler(product.getId(),
product.getUserId(), transferOrder.getUserId());
//자동 양도완료 관련 시스템 메세지 전송
chatService.createSystemMessageOfCompletedTransferByScheduler(product.getId(),
product.getUserId(), transferNego.getUser().getId());
}
negoRepository.saveAll(transferNegos);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ public interface NegoService {

NegoTestListResponse getNegoListForTest(); // 테스트용 모든 네고 기록 조회
List<Nego> findByStatusInAndProduct(List<NegotiationStatus> negotiationStatusList, Product product);

List<Nego> findAllByProductAndStatus(Product product, NegotiationStatus negotiationStatus);
Optional<Nego> findByUserIdAndProduct(Long userId, Product product);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
import site.goldenticket.domain.user.repository.UserRepository;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
Expand Down Expand Up @@ -67,11 +70,17 @@ public NegoResponse confirmPrice(Long negoId, PrincipalDetails principalDetails)
productService.updateProductForNego(product);
negoRepository.save(nego);

//구매자에게 네고 승인 및 결제 안내 알림 전송
//구매자에게 네고 승인 및 20분 내 결제 안내 알림 전송
ZoneId koreaZoneId = ZoneId.of("Asia/Seoul");
ZonedDateTime koreaZonedDateTimeOfExpirationTime = nego.getExpirationTime().atZone(koreaZoneId);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss");
String formattedDateTimeOfExpirationTime = koreaZonedDateTimeOfExpirationTime.format(formatter);
String formattedDateTimeWithoutSeconds =formattedDateTimeOfExpirationTime
.substring(0, formattedDateTimeOfExpirationTime.length() - 3);
alertService.createAlert(nego.getUser().getId(),
"'" + nego.getProduct().getAccommodationName() +
"(" + nego.getProduct().getRoomName() + ")'상품에 대한 네고 요청이 승인되었습니다. 해당상품을 "
+ nego.getExpirationTime() + "까지 결제를 완료해주세요.");
+ formattedDateTimeWithoutSeconds+ "까지 결제를 완료해주세요.");
} else {
// 다른 상태의 네고는 가격 승낙을 처리할 수 없음
throw new CustomException("네고를 승인할수 없습니다.", ErrorCode.CANNOT_CONFIRM_NEGO);
Expand Down Expand Up @@ -191,7 +200,7 @@ public PriceProposeResponse proposePrice(Long productId, PriceProposeRequest req

//판매자에게 네고 제안 알림 전송
alertService.createAlert(product.getUserId(),
"'" + product.getAccommodationName() + "(" + product.getRoomName()
"판매중인 상품 '" + product.getAccommodationName() + "(" + product.getRoomName()
+ ")'상품에 대한 네고 요청이 들어왔습니다.");

return PriceProposeResponse.fromEntity(userNego);
Expand Down Expand Up @@ -392,15 +401,8 @@ private void sendTransferCompleteAlerts(Nego nego, Product product, User user) {
// 판매자에게 정산 요청 알림 전송
alertService.createAlert(product.getUserId(),
"'" + product.getAccommodationName() + "(" + product.getRoomName()
+ ")'상품 양도가 완료되었습니다. 영업일 1일 이내 등록한 계좌 정보로 정산 금액이 입금됩니다."
+ ")'상품 양도가 완료되었습니다. 최대 9영업일 이내에 등록한 계좌 정보로 정산 금액이 입금됩니다."
+ "원활한 정산 진행을 위해 '마이페이지 - 나의 계좌'정보를 다시 한번 확인해주세요.");

// 판매자에게 계좌 등록 알림 전송
if (user != null && user.getAccountNumber() == null) {
alertService.createAlert(product.getUserId(),
"'" + product.getAccommodationName() + "(" + product.getRoomName()
+ ")'상품에 대한 원활한 정산을 위해 '마이페이지 > 내 계좌'에서 입금받으실 계좌를 등록해주세요.");
}
}

private void sendTransferCompleteAlertsForNotNego(Order order, Product product, User user) {
Expand All @@ -415,15 +417,8 @@ private void sendTransferCompleteAlertsForNotNego(Order order, Product product,
// 판매자에게 정산 요청 알림 전송
alertService.createAlert(product.getUserId(),
"'" + product.getAccommodationName() + "(" + product.getRoomName()
+ ")'상품 양도가 완료되었습니다. 영업일 1일 이내 등록한 계좌 정보로 정산 금액이 입금됩니다."
+ ")'상품 양도가 완료되었습니다. 최대 9영업일 등록한 계좌 정보로 정산 금액이 입금됩니다."
+ "원활한 정산 진행을 위해 '마이페이지 - 나의 계좌'정보를 다시 한번 확인해주세요.");

// 판매자에게 계좌 등록 알림 전송
if (user.getAccountNumber() == null) {
alertService.createAlert(product.getUserId(),
"'" + product.getAccommodationName() + "(" + product.getRoomName()
+ ")'상품에 대한 원활한 정산을 위해 '마이페이지 > 내 계좌'에서 입금받으실 계좌를 등록해주세요.");
}
}
}

Expand Down Expand Up @@ -503,6 +498,11 @@ public List<Nego> findByStatusInAndProduct(List<NegotiationStatus> negotiationSt
return negoRepository.findByStatusInAndProduct(negotiationStatusList, product);
}

@Override
public List<Nego> findAllByProductAndStatus(Product product, NegotiationStatus negotiationStatus) {
return negoRepository.findAllByProductAndStatus(product, negotiationStatus);
}

public Optional<Nego> findByUserIdAndProduct(Long userId, Product product) {
return negoRepository.findByUserIdAndProduct(userId, product);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package site.goldenticket.domain.payment.service;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -49,7 +52,8 @@ public class PaymentService {
private final AlertService alertService;
private final ChatService chatService;

public PaymentDetailResponse getPaymentDetail(Long productId, PrincipalDetails principalDetails) {
public PaymentDetailResponse getPaymentDetail(Long productId,
PrincipalDetails principalDetails) {
User user = userService.findById(principalDetails.getUserId());

Product product = productService.getProduct(productId);
Expand All @@ -58,7 +62,8 @@ public PaymentDetailResponse getPaymentDetail(Long productId, PrincipalDetails p
}

//상품상태 = 예약중, 해당 경우에 본인이 네고를 진행하였고 결제 대기중인지 확인
Optional<Nego> nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(user.getId(), product.getId());
Optional<Nego> nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(
user.getId(), product.getId());
if (product.getProductStatus() == ProductStatus.RESERVED) {
if (nego.isEmpty()) {
throw new CustomException(ErrorCode.PRODUCT_NOT_ON_SALE);
Expand All @@ -85,15 +90,16 @@ public PaymentDetailResponse getPaymentDetail(Long productId, PrincipalDetails p

Order savedOrder = orderRepository.save(order);

return PaymentDetailResponse.of(savedOrder.getId(), user, product, price, product.getYanoljaPrice());
return PaymentDetailResponse.of(savedOrder.getId(), user, product, price,
product.getYanoljaPrice());
}

public PaymentReadyResponse preparePayment(Long orderId, PrincipalDetails principalDetails) {

User user = userService.findById(principalDetails.getUserId());

Order order = orderRepository.findById(orderId).orElseThrow(
() -> new CustomException(ErrorCode.ORDER_NOT_FOUND)
() -> new CustomException(ErrorCode.ORDER_NOT_FOUND)
);

Product product = productService.getProduct(order.getProductId());
Expand All @@ -102,7 +108,8 @@ public PaymentReadyResponse preparePayment(Long orderId, PrincipalDetails princi
}

//상품상태 = 예약중, 해당 경우에 본인이 네고를 진행하였고 결제 대기중인지 확인
Optional<Nego> nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(user.getId(), product.getId());
Optional<Nego> nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(
user.getId(), product.getId());
if (product.getProductStatus() == ProductStatus.RESERVED) {
if (nego.isEmpty()) {
throw new CustomException(ErrorCode.PRODUCT_NOT_ON_SALE);
Expand All @@ -123,10 +130,10 @@ public PaymentResponse savePayment(PaymentRequest request, PrincipalDetails prin
Long userId = principalDetails.getUserId();

Payment payment = iamportRepository.findPaymentByImpUid(request.getImpUid())
.orElseThrow(() -> new CustomException(ErrorCode.PAYMENT_NOT_FOUND));
.orElseThrow(() -> new CustomException(ErrorCode.PAYMENT_NOT_FOUND));

Order order = orderRepository.findById(request.getOrderId())
.orElseThrow(() -> new CustomException(ErrorCode.ORDER_NOT_FOUND));
.orElseThrow(() -> new CustomException(ErrorCode.ORDER_NOT_FOUND));

Product product = productService.getProduct(order.getProductId());

Expand All @@ -148,7 +155,8 @@ public PaymentResponse savePayment(PaymentRequest request, PrincipalDetails prin
return PaymentResponse.failed();
}

Optional<Nego> nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(userId, product.getId());
Optional<Nego> nego = negoRepository.findFirstByUser_IdAndProduct_IdOrderByCreatedAtDesc(
userId, product.getId());

//상품상태 = 예약중
if (product.getProductStatus() == ProductStatus.RESERVED) {
Expand Down Expand Up @@ -180,18 +188,29 @@ public PaymentResponse savePayment(PaymentRequest request, PrincipalDetails prin
order.waitTransfer();
product.setProductStatus(ProductStatus.RESERVED);

//판매자에게 양도 알림 전송
//판매자에게 20분 내 양도 알림 전송
ZoneId koreaZoneId = ZoneId.of("Asia/Seoul");
ZonedDateTime koreaZonedDateTimeOfExpirationTime = order.getUpdatedAt().plusMinutes(20)
.atZone(koreaZoneId);
Integer hour = koreaZonedDateTimeOfExpirationTime.getHour();
Integer minute = koreaZonedDateTimeOfExpirationTime.getMinute();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss");
String formattedDateTimeOfExpirationTime = koreaZonedDateTimeOfExpirationTime.format(
formatter);
String formattedDateTimeWithoutSeconds =formattedDateTimeOfExpirationTime
.substring(0, formattedDateTimeOfExpirationTime.length() - 3);
alertService.createAlert(product.getUserId(),
product.getAccommodationName() + "(" + product.getRoomName() + ") "
+ "상품이 결제완료되었습니다." + order.getUpdatedAt().plusHours(3)
+ "까지 양도 신청을 완료해주세요. 양도 미신청 시, 자동 양도 신청됩니다.");
product.getAccommodationName() + "(" + product.getRoomName() + ") "
+ "상품이 결제완료되었습니다." + formattedDateTimeWithoutSeconds
+ "'까지 양도 여부를 선택해주세요. 미 입력 시 "+hour+":"+minute+" 이후 자동으로 양도가 진행됩니다.");

//채팅방 생성 + 시작 메세지 생성
if (!chatService.existsChatRoomByBuyerIdAndProductId(userId, product.getId())) {
ChatRoomResponse chatRoomResponse = chatService.createChatRoom(userId, product.getId());
chatService.createStartMessageOfNewChatRoom(chatRoomResponse.chatRoomId());
}
Long chatRoomId = chatService.getChatRoomByBuyerIdAndProductId(userId, product.getId()).getId();
Long chatRoomId = chatService.getChatRoomByBuyerIdAndProductId(userId, product.getId())
.getId();

return PaymentResponse.success(chatRoomId);
}
Expand All @@ -201,19 +220,20 @@ public Optional<Order> findByProductIdAndStatus(Long productId, OrderStatus orde
}

public void cancelPayment(String impUid) {
List<PaymentCancelDetail> paymentCancelDetails = iamportRepository.cancelPaymentByImpUid(impUid);
List<PaymentCancelDetail> paymentCancelDetails = iamportRepository.cancelPaymentByImpUid(
impUid);
paymentCancelDetailRepository.saveAll(paymentCancelDetails);

String pgTid = paymentCancelDetails.get(0).getPgTid();
Payment payment = paymentRepository.findByPgTid(pgTid).orElseThrow(
() -> new CustomException(ErrorCode.PAYMENT_NOT_FOUND)
() -> new CustomException(ErrorCode.PAYMENT_NOT_FOUND)
);
payment.cancelledPayment();
}

public Payment findByOrderId(Long orderId) {
return paymentRepository.findByOrderId(orderId).orElseThrow(
() -> new CustomException(ErrorCode.PAYMENT_NOT_FOUND)
() -> new CustomException(ErrorCode.PAYMENT_NOT_FOUND)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ public ProductDetailResponse getProduct(
boolean isSeller = isAuthenticated && principalDetails.getUserId().equals(product.getUserId());

NegoProductStatus negoProductStatus = null;
if(isSeller) {
List<NegotiationStatus> negotiationStatusList = Arrays.asList(NEGOTIATING, NEGOTIATION_CANCELLED);
List<Nego> negoList = negoService.findByStatusInAndProduct(negotiationStatusList, product);
if(!negoList.isEmpty()) {
if (isSeller) {
List<Nego> negoList = negoService.findAllByProductAndStatus(product, NegotiationStatus.NEGOTIATING);

if (!negoList.isEmpty()) {
negoProductStatus = NegoProductStatus.NEGOTIATION_HAVE;
}
} else {
}
else {
if(isAuthenticated) {
Optional<Nego> optionalNego = negoService.findByUserIdAndProduct(userId, product);
if(optionalNego.isPresent()) {
Expand Down
20 changes: 18 additions & 2 deletions src/test/java/site/goldenticket/common/utils/RestAssuredUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static ExtractableResponse<Response> restAssuredGet(String url) {
return RestAssured
.given().log().all()
.when()
.post(url)
.get(url)
.then().log().all()
.extract();
}
Expand All @@ -33,6 +33,22 @@ public static ExtractableResponse<Response> restAssuredGetWithToken(
.extract();
}

public static ExtractableResponse<Response> restAssuredGetWithTokenAndQueryParam(
String url,
String parameterName,
String parameterValues,
String accessToken
) {
return RestAssured
.given().log().all()
.header("Authorization", "Bearer " + accessToken)
.queryParam(parameterName, parameterValues)
.when()
.get(url)
.then().log().all()
.extract();
}

public static ExtractableResponse<Response> restAssuredPost(
String url,
Object request
Expand All @@ -58,7 +74,7 @@ public static ExtractableResponse<Response> restAssuredPostWithToken(
.contentType(APPLICATION_JSON_VALUE)
.body(request)
.when()
.get(url)
.post(url)
.then().log().all()
.extract();
}
Expand Down
Loading

0 comments on commit d8745a8

Please sign in to comment.