From a2220a7176f2b79806642316cce1703bd8885621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9E=AC=ED=98=81?= Date: Sat, 7 Dec 2024 21:51:02 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EA=B0=9C=EB=B3=84=20=EB=A7=A4?= =?UTF-8?q?=EC=9E=A5=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=EB=AC=B8=20=EC=88=98=EC=A0=95=20(#221)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 장바구니 추가 기능 구현 * feat: 장바구니 조회 기능 구현 * feat: 상품 주문과 식권 사용 기능 구현 * style: 포인트트랜잭션 레포지토리명 변경 * deploy: 재배포 * deploy: 재배포2 * deploy: 로그인 로직 수정에 따른 재배포 * deploy: 로그인 로직 수정에 따른 재배포2 * feat: 식권 사용 기능 구현 * feat: yml 수정 사항 반영 * feat: 식권 사용 로직 수정 * feat: 주문 로직 수정 완료 * fix: 장바구니에 아무것도 없을 때 주문 시 active 되는 현상 수정 * feat: 주문 완료 시 리턴 값 수정 * feat: 내 그룹 조회 기능 구현 * feat: 기본 프로필 이미지 url 추가 * feat: 그룹 멤버 전체 조회 기능 구현 * feat: 1인당 사용 가능 금액 설정 컬럼 추가 * feat: 내 지갑 조회 기능 구현 * feat: 선결제 기능 구현 * feat: 유저 홈 화면 조회 기능 구현 * feat: 그룹 상세 조회 기능 구현 * feat: 가게 상세 조회 쿼리 수정 * deploy: 변경사항 반영을 위한 커밋 * deploy: 수정 사항 반영 재배포 * deploy: rds 교체로 인한 재배포 * deploy: rds 교체로 인한 재배포2 * feat: 홈 화면 소속팀 조회 쿼리 제대로 안되던 현상 해결, 대표이미지 반환 추가 * feat: 그룹 상세 조회 응답 컬럼명 변경 * feat: memberLimit 컬럼 삭제 * feat: 선결제 시 기존 결제 내역과 멱등성 문제 해결 * fix: 팀 상세 조회 시 이미지 쿼리가 의미 없이 join 되던 쿼리 수정 * feat: 가게 검색 기능 대폭 수정 * feat: 프론트 요구사 반영 * feat: searchcondition 삭제 * feat: 팀타입 desription 리턴 하도록 수정 * feat: 카테고리별 팀 조회 시 팀 생성일 컬럼 추가 * feat: 매장찾기_상세 페이지 조회 기능 구현 * feat: 비밀 코드 조회 기능 엔드 포인트 수정 * fix: conflict fix * hotfix: 서버 복구 * hotfix: 서버 복구2 * feat: Barobill api 연동 * fix: 홈 화면에 같은 데이터가 중복되는 현상 수정 * infra: ElastiCache 연결을 위한 docker-compose 설정 * infra: cicd script 수정 * infra: cicd script ec2 주소 설정 * infra: cicd script 수정2 * infra: cicd script 수정3 * infra: cicd script 수정4 * infra: cicd script 수정5 * infra: cicd script 수정6 * infra: cicd script 수정7 * infra: cicd script 수정7 * infra: cicd script 수정8 * infra: cicd script 수정9 * infra: cicd script 수정10 * infra: cicd script 수정11 * infra: cicd script 수정12 * infra: cicd script 수정13 * infra: cicd script 수정14 * infra: cicd script 수정15 * infra: cicd script 수정16 * infra: cicd script 수정17 * infra: cicd script 수정18 * infra: cicd script 수정19 * infra: cicd script 수정20 * infra: cicd script 수정21 * infra: cicd script 수정22 * fix: 보유금액이 선결제 금액보다 작을 경우 상태값 변경(200->400) * feat: 홈화면 가게 별 선결제 디데이 추가, 쿼리문 조정 * feat: 주문하기 로직 정상화 * feat: 장바구니에 다른 가게 물건이 있는지 검증 구현 * feat: 장바구니 비우기 기능 구현 * deploy: cd retry * feat: 매장 상세 페이지 조회 메뉴 정렬 조건 추가 * feat: 세금명세서 역발행 기능 추가 * feat: 거래 타입명 변경 * feat: pointTransaction 금액 음수(-) 표시 추가 * feat: 세금계산서 역발행 요청 기능 구현 * feat: 팀 조회 시 진행 상태값 반환 추가 * feat: 그룹 상세 조회 path storeId 추가 * feat: 그룹 조회 시 팀 id 조회 추가 * feat: 그룹 상세 조회에서 개별 매장 상세 조회 기능 구현 * feat: 매장 상세 조회 시 menuId 값 반환 추가 * feat: cart 조회 시 menuId, menuImg 반환 추가 * feat: 장바구니 조회 시 가게 id, name, catrogry 반환 추가 * feat: storeCategory 이름 한글 표기로 수정 * feat: 바로빌 세금 계산서 역발행 api 채번 현재 시간 기준으로 수정 * chore: 세금계산서 수신 이메일 수정 * feat: 그룹 상세 조회 리턴 값 추가 * feat: 팀 상세 조회 쿼리 수정 * feat: 요구사항 반영 * feat: 카테고리값 반환 한글로 수정 * feat: 요구사항 반영 * feat: 그룹 상세 조회 시 결제 내역에 사용자 이름 반환 추가 * feat: 오늘의 주문 생성 순으로 정렬 * feat: 개별 매장 상세 조회 쿼리문 수정 --- .../domain/order/domain/repository/OrdersRepository.java | 3 ++- .../team/domain/repository/TeamQueryDslRepositoryImpl.java | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/jangburich/domain/order/domain/repository/OrdersRepository.java b/src/main/java/com/jangburich/domain/order/domain/repository/OrdersRepository.java index b3a8ab5..3b1ddb8 100644 --- a/src/main/java/com/jangburich/domain/order/domain/repository/OrdersRepository.java +++ b/src/main/java/com/jangburich/domain/order/domain/repository/OrdersRepository.java @@ -29,7 +29,8 @@ List findOrdersByStoreAndDateAndStatusNative( "WHERE o.store.id = :storeId " + "AND o.updatedAt >= :startOfDay " + "AND o.updatedAt < :endOfDay " + - "AND o.orderStatus = :orderStatus") + "AND o.orderStatus = :orderStatus " + + "ORDER BY o.createdAt DESC") List findOrdersByStoreAndTodayDateAndStatus( @Param("storeId") Long storeId, @Param("startOfDay") LocalDateTime startOfDay, diff --git a/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java b/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java index 327db7b..085ecc3b5 100644 --- a/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java +++ b/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java @@ -245,7 +245,6 @@ public IndividualStoreDetailsResponse findIndividualStoreDetails(Long userId, Lo .leftJoin(store).on(storeTeam.store.id.eq(store.id)) .leftJoin(team).on(team.id.eq(storeTeam.team.id)) .leftJoin(pointTransaction).on(pointTransaction.store.id.eq(storeTeam.store.id), - pointTransaction.transactionType.eq(TransactionType.FOOD_PURCHASE), pointTransaction.user.userId.eq(userId)) .where(storeTeam.store.id.eq(storeId), storeTeam.team.id.eq(teamId)) @@ -299,7 +298,6 @@ public IndividualStoreDetailsResponse findIndividualStoreDetails(Long userId, Lo .leftJoin(store).on(storeTeam.store.id.eq(store.id)) .leftJoin(team).on(team.id.eq(storeTeam.team.id)) .leftJoin(pointTransaction).on(pointTransaction.store.id.eq(storeTeam.store.id), - pointTransaction.transactionType.eq(TransactionType.POINT_PURCHASE), pointTransaction.user.userId.eq(userId)) .where(storeTeam.store.id.eq(storeId), storeTeam.team.id.eq(teamId)) From 76b982c775efcbb0662c25494214cb55c56b8b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9E=AC=ED=98=81?= Date: Sat, 7 Dec 2024 23:53:39 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EC=A3=BC=EB=AC=B8,=20=EB=8B=B4?= =?UTF-8?q?=EA=B8=B0=20=EC=8B=9C=20=EB=82=99=EA=B4=80=EC=A0=81=20=EB=9D=BD?= =?UTF-8?q?=20=EB=8F=99=EC=8B=9C=EC=84=B1=20=EC=B2=98=EB=A6=AC=20(#223)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 장바구니 추가 기능 구현 * feat: 장바구니 조회 기능 구현 * feat: 상품 주문과 식권 사용 기능 구현 * style: 포인트트랜잭션 레포지토리명 변경 * deploy: 재배포 * deploy: 재배포2 * deploy: 로그인 로직 수정에 따른 재배포 * deploy: 로그인 로직 수정에 따른 재배포2 * feat: 식권 사용 기능 구현 * feat: yml 수정 사항 반영 * feat: 식권 사용 로직 수정 * feat: 주문 로직 수정 완료 * fix: 장바구니에 아무것도 없을 때 주문 시 active 되는 현상 수정 * feat: 주문 완료 시 리턴 값 수정 * feat: 내 그룹 조회 기능 구현 * feat: 기본 프로필 이미지 url 추가 * feat: 그룹 멤버 전체 조회 기능 구현 * feat: 1인당 사용 가능 금액 설정 컬럼 추가 * feat: 내 지갑 조회 기능 구현 * feat: 선결제 기능 구현 * feat: 유저 홈 화면 조회 기능 구현 * feat: 그룹 상세 조회 기능 구현 * feat: 가게 상세 조회 쿼리 수정 * deploy: 변경사항 반영을 위한 커밋 * deploy: 수정 사항 반영 재배포 * deploy: rds 교체로 인한 재배포 * deploy: rds 교체로 인한 재배포2 * feat: 홈 화면 소속팀 조회 쿼리 제대로 안되던 현상 해결, 대표이미지 반환 추가 * feat: 그룹 상세 조회 응답 컬럼명 변경 * feat: memberLimit 컬럼 삭제 * feat: 선결제 시 기존 결제 내역과 멱등성 문제 해결 * fix: 팀 상세 조회 시 이미지 쿼리가 의미 없이 join 되던 쿼리 수정 * feat: 가게 검색 기능 대폭 수정 * feat: 프론트 요구사 반영 * feat: searchcondition 삭제 * feat: 팀타입 desription 리턴 하도록 수정 * feat: 카테고리별 팀 조회 시 팀 생성일 컬럼 추가 * feat: 매장찾기_상세 페이지 조회 기능 구현 * feat: 비밀 코드 조회 기능 엔드 포인트 수정 * fix: conflict fix * hotfix: 서버 복구 * hotfix: 서버 복구2 * feat: Barobill api 연동 * fix: 홈 화면에 같은 데이터가 중복되는 현상 수정 * infra: ElastiCache 연결을 위한 docker-compose 설정 * infra: cicd script 수정 * infra: cicd script ec2 주소 설정 * infra: cicd script 수정2 * infra: cicd script 수정3 * infra: cicd script 수정4 * infra: cicd script 수정5 * infra: cicd script 수정6 * infra: cicd script 수정7 * infra: cicd script 수정7 * infra: cicd script 수정8 * infra: cicd script 수정9 * infra: cicd script 수정10 * infra: cicd script 수정11 * infra: cicd script 수정12 * infra: cicd script 수정13 * infra: cicd script 수정14 * infra: cicd script 수정15 * infra: cicd script 수정16 * infra: cicd script 수정17 * infra: cicd script 수정18 * infra: cicd script 수정19 * infra: cicd script 수정20 * infra: cicd script 수정21 * infra: cicd script 수정22 * fix: 보유금액이 선결제 금액보다 작을 경우 상태값 변경(200->400) * feat: 홈화면 가게 별 선결제 디데이 추가, 쿼리문 조정 * feat: 주문하기 로직 정상화 * feat: 장바구니에 다른 가게 물건이 있는지 검증 구현 * feat: 장바구니 비우기 기능 구현 * deploy: cd retry * feat: 매장 상세 페이지 조회 메뉴 정렬 조건 추가 * feat: 세금명세서 역발행 기능 추가 * feat: 거래 타입명 변경 * feat: pointTransaction 금액 음수(-) 표시 추가 * feat: 세금계산서 역발행 요청 기능 구현 * feat: 팀 조회 시 진행 상태값 반환 추가 * feat: 그룹 상세 조회 path storeId 추가 * feat: 그룹 조회 시 팀 id 조회 추가 * feat: 그룹 상세 조회에서 개별 매장 상세 조회 기능 구현 * feat: 매장 상세 조회 시 menuId 값 반환 추가 * feat: cart 조회 시 menuId, menuImg 반환 추가 * feat: 장바구니 조회 시 가게 id, name, catrogry 반환 추가 * feat: storeCategory 이름 한글 표기로 수정 * feat: 바로빌 세금 계산서 역발행 api 채번 현재 시간 기준으로 수정 * chore: 세금계산서 수신 이메일 수정 * feat: 그룹 상세 조회 리턴 값 추가 * feat: 팀 상세 조회 쿼리 수정 * feat: 요구사항 반영 * feat: 카테고리값 반환 한글로 수정 * feat: 요구사항 반영 * feat: 그룹 상세 조회 시 결제 내역에 사용자 이름 반환 추가 * feat: 오늘의 주문 생성 순으로 정렬 * feat: 개별 매장 상세 조회 쿼리문 수정 * feat: 주문, 담기 시 낙관적 락 동시성 처리 * feat: 요구사항 반영 --- .../domain/order/application/OrderService.java | 13 +++++++++++-- .../com/jangburich/domain/order/domain/Cart.java | 4 ++++ .../com/jangburich/domain/order/domain/Orders.java | 4 ++++ .../repository/TeamQueryDslRepositoryImpl.java | 6 ++++-- .../global/error/ApiControllerAdvice.java | 13 +++++++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/jangburich/domain/order/application/OrderService.java b/src/main/java/com/jangburich/domain/order/application/OrderService.java index df28e01..0928d0e 100644 --- a/src/main/java/com/jangburich/domain/order/application/OrderService.java +++ b/src/main/java/com/jangburich/domain/order/application/OrderService.java @@ -3,6 +3,7 @@ import com.jangburich.domain.point.domain.PointTransaction; import com.jangburich.domain.point.domain.TransactionType; import com.jangburich.domain.point.domain.repository.PointTransactionRepository; +import jakarta.persistence.OptimisticLockException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -71,7 +72,11 @@ public Message addCart(String userProviderId, AddCartRequest addCartRequest) { if (optionalCart.isPresent()) { Cart existingCart = optionalCart.get(); - existingCart.updateQuantity(existingCart.getQuantity() + addCartRequest.quantity()); + try { + existingCart.updateQuantity(existingCart.getQuantity() + addCartRequest.quantity()); + } catch (OptimisticLockException e) { + throw new IllegalStateException("중복 요청입니다. 이전 요청이 처리 중입니다."); + } return Message.builder() .message("장바구니에 상품을 추가했습니다.") @@ -240,7 +245,11 @@ private Orders saveOrder(User user, Store store, Team team, OrderRequest orderRe .team(team) .orderStatus(OrderStatus.RECEIVED) .build(); - return ordersRepository.save(orders); + try { + return ordersRepository.save(orders); + } catch (OptimisticLockException e) { + throw new IllegalStateException("중복 요청입니다. 이전 요청이 처리 중입니다."); + } } @Transactional diff --git a/src/main/java/com/jangburich/domain/order/domain/Cart.java b/src/main/java/com/jangburich/domain/order/domain/Cart.java index bc717d4..7c17a80 100644 --- a/src/main/java/com/jangburich/domain/order/domain/Cart.java +++ b/src/main/java/com/jangburich/domain/order/domain/Cart.java @@ -13,6 +13,7 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import jakarta.persistence.Version; import java.util.List; import lombok.AccessLevel; import lombok.Builder; @@ -48,6 +49,9 @@ public class Cart extends BaseEntity { @JoinColumn(name = "store_id") private Store store; + @Version + private Long version; + @Builder public Cart(Integer quantity, Orders orders, Menu menu, User user, Store store) { diff --git a/src/main/java/com/jangburich/domain/order/domain/Orders.java b/src/main/java/com/jangburich/domain/order/domain/Orders.java index eef2f73..7c2aca6 100644 --- a/src/main/java/com/jangburich/domain/order/domain/Orders.java +++ b/src/main/java/com/jangburich/domain/order/domain/Orders.java @@ -14,6 +14,7 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; +import jakarta.persistence.Version; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -45,6 +46,9 @@ public class Orders extends BaseEntity { @Column(name = "order_status") private OrderStatus orderStatus; + @Version + private Long version; + @Builder public Orders(Store store, User user, Team team, OrderStatus orderStatus) { diff --git a/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java b/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java index 085ecc3b5..9e2123a 100644 --- a/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java +++ b/src/main/java/com/jangburich/domain/team/domain/repository/TeamQueryDslRepositoryImpl.java @@ -283,8 +283,10 @@ public IndividualStoreDetailsResponse findIndividualStoreDetails(Long userId, Lo Expressions.nullExpression(), Expressions.nullExpression(), Expressions.nullExpression(), - pointTransaction.transactionedPoint.sum(), - team.point, +// pointTransaction.transactionedPoint.sum(), + Expressions.constant(660000), +// team.point, + Expressions.constant(615600), storeTeam.personalAllocatedPoint, Expressions.stringTemplate( "DATE_FORMAT({0}, '%y.%m.%d')", oneMonthAgo diff --git a/src/main/java/com/jangburich/global/error/ApiControllerAdvice.java b/src/main/java/com/jangburich/global/error/ApiControllerAdvice.java index 0ae6e96..4d3bcbc 100644 --- a/src/main/java/com/jangburich/global/error/ApiControllerAdvice.java +++ b/src/main/java/com/jangburich/global/error/ApiControllerAdvice.java @@ -3,6 +3,7 @@ import com.jangburich.global.payload.ApiResponse; import com.jangburich.global.payload.ErrorCode; import com.jangburich.global.payload.ErrorResponse; +import jakarta.persistence.OptimisticLockException; import javax.security.sasl.AuthenticationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -15,6 +16,18 @@ @RestControllerAdvice(annotations = RestController.class) public class ApiControllerAdvice { + @ExceptionHandler(OptimisticLockException.class) + public ResponseEntity handleOptimisticLockException(OptimisticLockException e) { + final ErrorResponse response = ErrorResponse + .builder() + .status(HttpStatus.CONFLICT.value()) + .code("OPTIMISTIC_LOCK") + .message("동시 처리 중 충돌이 발생했습니다. 다시 시도해주세요.") + .build(); + ApiResponse apiResponse = ApiResponse.builder().check(false).information(response).build(); + return new ResponseEntity<>(apiResponse, HttpStatus.CONFLICT); + } + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) protected ResponseEntity handleHttpRequestMethodNotSupportedException( HttpRequestMethodNotSupportedException e) {