-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] 배송지·주문·결제 API 구현 #705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
CUCU7103
wants to merge
8
commits into
dev
Choose a base branch
from
feature/order-create
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
753c3c4
[Feat] 주문서 미리보기 및 주문 생성 API 구현
CUCU7103 7908309
[Feat] 배송지 CRUD API 구현
CUCU7103 3466550
[Fix] 배송지·주문 API 버그 수정 및 테스트 추가
CUCU7103 5c02b7f
[Feat] 고객 결제 승인 API 구현
CUCU7103 3bf9d0c
[Chore] Flyway 마이그레이션 번호 충돌 방지를 위해 V59→V60, V60→V61, V61→V62로 재번호
CUCU7103 fbc72c1
[Chore] orders 테이블 order_group_id NOT NULL 및 order_number UNIQUE 제약 마…
CUCU7103 fcc1651
[Fix] CodeRabbit 리뷰 버그 5건 수정
CUCU7103 ce26114
[Test] orders NOT NULL 제약 대응 테스트 픽스처 및 통합 테스트 수정
CUCU7103 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
src/main/java/com/bbangle/bbangle/member/customer/controller/DeliveryAddressController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| package com.bbangle.bbangle.member.customer.controller; | ||
|
|
||
| import com.bbangle.bbangle.common.dto.CommonResult; | ||
| import com.bbangle.bbangle.common.dto.ListResult; | ||
| import com.bbangle.bbangle.common.dto.SingleResult; | ||
| import com.bbangle.bbangle.common.service.ResponseService; | ||
| import com.bbangle.bbangle.member.customer.controller.dto.request.DeliveryAddressSaveRequest; | ||
| import com.bbangle.bbangle.member.customer.controller.dto.response.DeliveryAddressResponse; | ||
| import com.bbangle.bbangle.member.customer.service.DeliveryAddressService; | ||
| import io.swagger.v3.oas.annotations.Operation; | ||
| import jakarta.validation.Valid; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.security.core.annotation.AuthenticationPrincipal; | ||
| import org.springframework.web.bind.annotation.DeleteMapping; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.PatchMapping; | ||
| import org.springframework.web.bind.annotation.PathVariable; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.PutMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| @RequestMapping("/api/v1/customer/delivery-addresses") | ||
| public class DeliveryAddressController { | ||
|
|
||
| private final DeliveryAddressService deliveryAddressService; | ||
| private final ResponseService responseService; | ||
|
|
||
| @GetMapping | ||
| @Operation(summary = "배송지 목록 조회") | ||
| public ListResult<DeliveryAddressResponse> getDeliveryAddresses( | ||
| @AuthenticationPrincipal Long memberId | ||
| ) { | ||
| return responseService.getListResult( | ||
| deliveryAddressService.getDeliveryAddresses(memberId) | ||
| ); | ||
| } | ||
|
|
||
| @PostMapping | ||
| @Operation(summary = "배송지 추가") | ||
| public SingleResult<DeliveryAddressResponse> addDeliveryAddress( | ||
| @Valid @RequestBody DeliveryAddressSaveRequest request, | ||
| @AuthenticationPrincipal Long memberId | ||
| ) { | ||
| return responseService.getSingleResult( | ||
| deliveryAddressService.addDeliveryAddress(memberId, request) | ||
| ); | ||
| } | ||
|
|
||
| @PutMapping("/{id}") | ||
| @Operation(summary = "배송지 수정") | ||
| public SingleResult<DeliveryAddressResponse> updateDeliveryAddress( | ||
| @PathVariable Long id, | ||
| @Valid @RequestBody DeliveryAddressSaveRequest request, | ||
| @AuthenticationPrincipal Long memberId | ||
| ) { | ||
| return responseService.getSingleResult( | ||
| deliveryAddressService.updateDeliveryAddress(memberId, id, request) | ||
| ); | ||
| } | ||
|
|
||
| @DeleteMapping("/{id}") | ||
| @Operation(summary = "배송지 삭제") | ||
| public CommonResult deleteDeliveryAddress( | ||
| @PathVariable Long id, | ||
| @AuthenticationPrincipal Long memberId | ||
| ) { | ||
| deliveryAddressService.deleteDeliveryAddress(memberId, id); | ||
| return responseService.getSuccessResult(); | ||
| } | ||
|
|
||
| @PatchMapping("/{id}/default") | ||
| @Operation(summary = "기본 배송지 설정") | ||
| public CommonResult setDefaultDeliveryAddress( | ||
| @PathVariable Long id, | ||
| @AuthenticationPrincipal Long memberId | ||
| ) { | ||
| deliveryAddressService.setDefaultDeliveryAddress(memberId, id); | ||
| return responseService.getSuccessResult(); | ||
| } | ||
| } |
15 changes: 15 additions & 0 deletions
15
...om/bbangle/bbangle/member/customer/controller/dto/request/DeliveryAddressSaveRequest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.bbangle.bbangle.member.customer.controller.dto.request; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.Size; | ||
|
|
||
| public record DeliveryAddressSaveRequest( | ||
| @NotBlank @Size(max = 50) String addressName, | ||
| @NotBlank @Size(max = 100) String recipientName, | ||
| @NotBlank @Size(max = 20) String phone, | ||
| @NotBlank @Size(max = 255) String address, | ||
| @Size(max = 255) String addressDetail, | ||
| @Size(max = 10) String zipCode, | ||
| Boolean isDefault | ||
| ) { | ||
| } |
27 changes: 27 additions & 0 deletions
27
.../com/bbangle/bbangle/member/customer/controller/dto/response/DeliveryAddressResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.bbangle.bbangle.member.customer.controller.dto.response; | ||
|
|
||
| import com.bbangle.bbangle.member.domain.MemberDeliveryAddress; | ||
|
|
||
| public record DeliveryAddressResponse( | ||
| Long id, | ||
| String addressName, | ||
| boolean isDefault, | ||
| String recipientName, | ||
| String phone, | ||
| String address, | ||
| String addressDetail, | ||
| String zipCode | ||
| ) { | ||
| public static DeliveryAddressResponse from(MemberDeliveryAddress entity) { | ||
| return new DeliveryAddressResponse( | ||
| entity.getId(), | ||
| entity.getAddressName(), | ||
| entity.isDefault(), | ||
| entity.getRecipientName(), | ||
| entity.getPhone(), | ||
| entity.getAddress(), | ||
| entity.getAddressDetail(), | ||
| entity.getZipCode() | ||
| ); | ||
| } | ||
| } |
114 changes: 114 additions & 0 deletions
114
src/main/java/com/bbangle/bbangle/member/customer/service/DeliveryAddressService.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| package com.bbangle.bbangle.member.customer.service; | ||
|
|
||
| import com.bbangle.bbangle.exception.BbangleErrorCode; | ||
| import com.bbangle.bbangle.exception.BbangleException; | ||
| import com.bbangle.bbangle.member.customer.controller.dto.request.DeliveryAddressSaveRequest; | ||
| import com.bbangle.bbangle.member.customer.controller.dto.response.DeliveryAddressResponse; | ||
| import com.bbangle.bbangle.member.domain.Member; | ||
| import com.bbangle.bbangle.member.domain.MemberDeliveryAddress; | ||
| import com.bbangle.bbangle.member.repository.MemberDeliveryAddressRepository; | ||
| import com.bbangle.bbangle.member.repository.MemberRepository; | ||
| import java.util.List; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| @Transactional | ||
| public class DeliveryAddressService { | ||
|
|
||
| private final MemberDeliveryAddressRepository deliveryAddressRepository; | ||
| private final MemberRepository memberRepository; | ||
|
|
||
| @Transactional(readOnly = true) | ||
| public List<DeliveryAddressResponse> getDeliveryAddresses(Long memberId) { | ||
| return deliveryAddressRepository.findAllByMemberIdAndIsDeletedFalse(memberId) | ||
| .stream() | ||
| .map(DeliveryAddressResponse::from) | ||
| .toList(); | ||
| } | ||
|
|
||
| public DeliveryAddressResponse addDeliveryAddress(Long memberId, DeliveryAddressSaveRequest request) { | ||
| boolean makeDefault = Boolean.TRUE.equals(request.isDefault()); | ||
|
|
||
| // isDefault=true일 때 Member 행 잠금을 직렬화 포인트로 사용해 동시 insert 경합 방지 | ||
| Member member = makeDefault | ||
| ? memberRepository.findByIdWithLock(memberId) | ||
| .orElseThrow(() -> new BbangleException(BbangleErrorCode.NOTFOUND_MEMBER)) | ||
| : memberRepository.findById(memberId) | ||
| .orElseThrow(() -> new BbangleException(BbangleErrorCode.NOTFOUND_MEMBER)); | ||
|
|
||
| if (makeDefault) { | ||
| deliveryAddressRepository.findByMemberIdAndIsDefaultTrueAndIsDeletedFalse(memberId) | ||
| .ifPresent(MemberDeliveryAddress::unsetDefault); | ||
| } | ||
|
|
||
| MemberDeliveryAddress address = MemberDeliveryAddress.builder() | ||
| .member(member) | ||
| .addressName(request.addressName()) | ||
| .recipientName(request.recipientName()) | ||
| .phone(request.phone()) | ||
| .address(request.address()) | ||
| .addressDetail(request.addressDetail()) | ||
| .zipCode(request.zipCode()) | ||
| .isDefault(makeDefault) | ||
| .build(); | ||
|
|
||
| return DeliveryAddressResponse.from(deliveryAddressRepository.save(address)); | ||
| } | ||
|
|
||
| public DeliveryAddressResponse updateDeliveryAddress(Long memberId, Long addressId, | ||
| DeliveryAddressSaveRequest request) { | ||
| MemberDeliveryAddress address = findOwnedAddress(memberId, addressId); | ||
|
|
||
| address.update( | ||
| request.addressName(), | ||
| request.recipientName(), | ||
| request.phone(), | ||
| request.address(), | ||
| request.addressDetail(), | ||
| request.zipCode() | ||
| ); | ||
|
|
||
| // isDefault가 null이면 기존 기본 배송지 상태 유지 | ||
| if (request.isDefault() != null) { | ||
| boolean makeDefault = request.isDefault(); | ||
| if (makeDefault && !address.isDefault()) { | ||
| // Member 행 잠금으로 직렬화 후 기존 기본 배송지 해제 | ||
| memberRepository.findByIdWithLock(memberId) | ||
| .orElseThrow(() -> new BbangleException(BbangleErrorCode.NOTFOUND_MEMBER)); | ||
| deliveryAddressRepository.findByMemberIdAndIsDefaultTrueAndIsDeletedFalse(memberId) | ||
| .ifPresent(MemberDeliveryAddress::unsetDefault); | ||
| address.setDefault(); | ||
| } else if (!makeDefault) { | ||
| address.unsetDefault(); | ||
| } | ||
| } | ||
|
|
||
| return DeliveryAddressResponse.from(address); | ||
| } | ||
|
|
||
| public void deleteDeliveryAddress(Long memberId, Long addressId) { | ||
| MemberDeliveryAddress address = findOwnedAddress(memberId, addressId); | ||
| address.delete(); | ||
| } | ||
|
|
||
| public void setDefaultDeliveryAddress(Long memberId, Long addressId) { | ||
| // Member 행 잠금을 먼저 획득해 동시 기본 배송지 변경 직렬화 | ||
| memberRepository.findByIdWithLock(memberId) | ||
| .orElseThrow(() -> new BbangleException(BbangleErrorCode.NOTFOUND_MEMBER)); | ||
|
|
||
| MemberDeliveryAddress address = findOwnedAddress(memberId, addressId); | ||
| deliveryAddressRepository.findByMemberIdAndIsDefaultTrueAndIsDeletedFalse(memberId) | ||
| .ifPresent(MemberDeliveryAddress::unsetDefault); | ||
| address.setDefault(); | ||
| } | ||
|
|
||
| // 소유권을 조회 조건에 포함해 타인 주소 접근 시에도 동일한 404 반환 (ID 열거 방지) | ||
| private MemberDeliveryAddress findOwnedAddress(Long memberId, Long addressId) { | ||
| return deliveryAddressRepository | ||
| .findByIdAndMemberIdAndIsDeletedFalse(addressId, memberId) | ||
| .orElseThrow(() -> new BbangleException(BbangleErrorCode.DELIVERY_ADDRESS_NOT_FOUND)); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.