Skip to content

Commit

Permalink
Merge branch 'develop' into feature/310-validate-funding-contribute-a…
Browse files Browse the repository at this point in the history
…mount
  • Loading branch information
YeaChan05 authored Jul 18, 2024
2 parents da0d169 + 6ab57cc commit 1e15c0b
Show file tree
Hide file tree
Showing 20 changed files with 195 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.requestMatchers(ACTUATOR).permitAll()
.requestMatchers(METRICS).permitAll()
.requestMatchers(FAVICON_URL).permitAll()
.requestMatchers(API_V_1 + "oauth/login").permitAll()
.requestMatchers(API_V_1 + "oauth/logout").authenticated()
.requestMatchers(API_V_1 + "oauth/reissue").permitAll()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class CartResponse {
private String optionName;
private String optionDetailName;
private Long totalPrice;
private boolean isSelected;

public static CartResponse from(Cart cart){
Long totalPrice = cart.calculateTotalPrice();
Expand All @@ -38,6 +39,7 @@ public static CartResponse from(Cart cart){
.totalPrice(totalPrice)
.optionName(cart.getOption() != null ? cart.getOption().getName() : null)
.optionDetailName(cart.getOptionDetail() != null ? cart.getOptionDetail().getName() : null)
.isSelected(cart.isSelected())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,6 @@ public FundingDetail(final Member member,
this.rate = calculateRate(this.amount);
}

public void increaseAmountAndRate(final Long amount) {
if (amount != null) {
this.rate += calculateRate(amount);
this.amount += amount;
}
}

public void partialCancel(final Long amount) {
this.rate -= calculateRate(amount);
this.amount -= amount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

@Getter
public enum FundingDetailErrorCode implements ErrorCode {
NOT_FOUND(HttpStatus.NOT_FOUND, "기여한 펀딩 내역을 찾을 수 없습니다.");
NOT_FOUND(HttpStatus.NOT_FOUND, "기여한 펀딩 내역을 찾을 수 없습니다."),
INVALID_CANCEL_AMOUNT(HttpStatus.BAD_REQUEST, "환불 금액은 기여 금액보다 클 수 없습니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.kakaoshare.backend.domain.gift.dto.inquiry.history;

import com.querydsl.core.annotations.QueryProjection;
import org.kakaoshare.backend.domain.gift.entity.Gift;
import org.kakaoshare.backend.domain.product.dto.ProductDto;

import java.time.LocalDateTime;
Expand All @@ -15,4 +16,15 @@ public record GiftDto(Long giftId,
@QueryProjection
public GiftDto {
}

public static GiftDto from(final Gift gift) {
return new GiftDto(
gift.getGiftId(),
gift.getExpiredAt(),
gift.getCreatedAt(),
gift.getReceipt().getRecipient().getName(),
gift.getReceipt().getRecipient().getProviderId(),
ProductDto.from(gift.getReceipt().getProduct())
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.kakaoshare.backend.domain.gift.entity.GiftStatus;
import org.kakaoshare.backend.domain.gift.exception.GiftErrorCode;
import org.kakaoshare.backend.domain.gift.exception.GiftException;
import org.kakaoshare.backend.domain.member.entity.QMember;
import org.kakaoshare.backend.domain.product.dto.QProductDto;
import org.kakaoshare.backend.domain.product.entity.Product;
import org.kakaoshare.backend.domain.product.entity.ProductThumbnail;
Expand All @@ -28,14 +29,16 @@
import static org.kakaoshare.backend.common.util.RepositoryUtils.eqExpression;
import static org.kakaoshare.backend.common.util.RepositoryUtils.toPage;
import static org.kakaoshare.backend.domain.gift.entity.QGift.gift;
import static org.kakaoshare.backend.domain.member.entity.QMember.member;
import static org.kakaoshare.backend.domain.product.entity.QProduct.product;
import static org.kakaoshare.backend.domain.receipt.entity.QReceipt.receipt;


@Repository
@RequiredArgsConstructor
public class GiftRepositoryCustomImpl implements GiftRepositoryCustom {
private static final QMember receiver = new QMember("receiver");
private static final QMember recipient = new QMember("recipient");

private final JPAQueryFactory queryFactory;

@Override
Expand Down Expand Up @@ -89,9 +92,10 @@ private JPAQuery<?> createHistoryBaseQuery(final String providerId, final GiftSt
.from(gift)
.innerJoin(gift.receipt, receipt)
.innerJoin(receipt.product, product)
.innerJoin(receipt.recipient, member)
.innerJoin(receipt.recipient, recipient)
.innerJoin(receipt.receiver, receiver)
.where(
eqExpression(receipt.recipient.providerId, providerId),
eqExpression(receiver.providerId, providerId),
eqExpression(gift.status, status)
);
}
Expand Down Expand Up @@ -126,8 +130,8 @@ private QGiftDto getGiftDto() {
gift.giftId,
gift.expiredAt,
gift.createdAt,
member.name,
member.providerId,
recipient.name,
recipient.providerId,
getProductDto()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,20 @@
import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResponse;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.logout.OAuthLogoutRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResponse;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResult;
import org.kakaoshare.backend.domain.member.dto.oauth.logout.OAuthSocialLogoutRequest;
import org.kakaoshare.backend.domain.member.service.oauth.OAuthService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import static org.kakaoshare.backend.domain.member.controller.RefreshTokenCookieProvider.REFRESH_TOKEN;

@RequiredArgsConstructor
@RequestMapping("/api/v1/oauth")
Expand All @@ -20,29 +28,40 @@ public class OAuthController {
private final RefreshTokenCookieProvider refreshTokenCookieProvider;

@PostMapping("/login")
public ResponseEntity<OAuthLoginResponse> login(@RequestBody @Valid final OAuthLoginRequest oAuthLoginRequest) {
public ResponseEntity<?> login(@RequestBody @Valid final OAuthLoginRequest oAuthLoginRequest) {
final OAuthLoginResponse loginResponse = oAuthService.login(oAuthLoginRequest);
final ResponseCookie cookie = refreshTokenCookieProvider.createCookie(loginResponse.refreshToken());
return ResponseEntity.ok()
.body(oAuthService.login(oAuthLoginRequest));
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(loginResponse);
}

@PostMapping("/logout")
public ResponseEntity<Void> logout(@RequestBody final OAuthLogoutRequest oAuthLogoutRequest) {
oAuthService.logout(oAuthLogoutRequest);
public ResponseEntity<?> logout(
@CookieValue(value = REFRESH_TOKEN, required = false) final String refreshTokenValue
) {
oAuthService.logout(refreshTokenValue);
return ResponseEntity.noContent()
.header(HttpHeaders.SET_COOKIE, refreshTokenCookieProvider.createLogoutCookie().toString())
.build();
}

@PostMapping("/social/logout")
public ResponseEntity<Void> socialLogout(@RequestBody final OAuthSocialLogoutRequest oAuthSocialLogoutRequest) {
public ResponseEntity<?> socialLogout(@RequestBody final OAuthSocialLogoutRequest oAuthSocialLogoutRequest) {
oAuthService.socialLogout(oAuthSocialLogoutRequest);
return ResponseEntity.noContent()
.build();
}

@PostMapping("/reissue")
public ResponseEntity<?> reissue(@RequestBody final ReissueRequest reissueRequest) {
public ResponseEntity<?> reissue(
@CookieValue(value = REFRESH_TOKEN, required = false) final String refreshTokenValue
) {
final ReissueResult reissueResult = oAuthService.reissue(refreshTokenValue);
final ResponseCookie cookie = refreshTokenCookieProvider.createCookie(reissueResult.refreshToken());
return ResponseEntity.ok()
.body(oAuthService.reissue(reissueRequest));
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(ReissueResponse.from(reissueResult));
}

@PostMapping("/social/reissue")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.kakaoshare.backend.domain.member.controller;

import org.apache.logging.log4j.util.Strings;
import org.kakaoshare.backend.domain.member.dto.oauth.token.RefreshTokenDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.server.Cookie;
import org.springframework.http.ResponseCookie;
Expand All @@ -20,8 +21,8 @@ public RefreshTokenCookieProvider(@Value("${security.token.refresh.expire-time}"
this.expireTime = expireTime;
}

public ResponseCookie createCookie(final String tokenValue) {
return createTokenCookieBuilder(tokenValue)
public ResponseCookie createCookie(final RefreshTokenDto refreshToken) {
return createTokenCookieBuilder(refreshToken.value())
.maxAge(expireTime)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package org.kakaoshare.backend.domain.member.dto.oauth.issue;

import org.kakaoshare.backend.domain.member.dto.oauth.token.RefreshTokenDto;
import org.kakaoshare.backend.domain.member.entity.token.RefreshToken;

public record ReissueResponse(String accessToken, RefreshTokenDto refreshToken) {
public static ReissueResponse of(final String accessToken, final RefreshToken refreshToken) {
return new ReissueResponse(accessToken, RefreshTokenDto.from(refreshToken));
public record ReissueResponse(String accessToken) {
public static ReissueResponse from(final ReissueResult reissueResult) {
return new ReissueResponse(reissueResult.accessToken());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.kakaoshare.backend.domain.member.dto.oauth.issue;

import org.kakaoshare.backend.domain.member.dto.oauth.token.RefreshTokenDto;
import org.kakaoshare.backend.domain.member.entity.token.RefreshToken;

public record ReissueResult(String accessToken, RefreshTokenDto refreshToken) {
public static ReissueResult of(final String accessToken, final RefreshToken refreshToken) {
return new ReissueResult(accessToken, RefreshTokenDto.from(refreshToken));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResponse;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueResponse;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResponse;
import org.kakaoshare.backend.domain.member.dto.oauth.logout.OAuthLogoutRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResult;
import org.kakaoshare.backend.domain.member.dto.oauth.logout.OAuthSocialLogoutRequest;
import org.kakaoshare.backend.domain.member.dto.oauth.profile.OAuthProfile;
import org.kakaoshare.backend.domain.member.dto.oauth.profile.OAuthProfileFactory;
Expand Down Expand Up @@ -56,8 +54,7 @@ public OAuthLoginResponse login(final OAuthLoginRequest oAuthLoginRequest) {
}

@Transactional
public void logout(final OAuthLogoutRequest oAuthLogoutRequest) {
final String refreshTokenValue = oAuthLogoutRequest.refreshToken();
public void logout(final String refreshTokenValue) {
final RefreshToken refreshToken = findRefreshTokenByValue(refreshTokenValue);
refreshTokenRepository.delete(refreshToken);
}
Expand All @@ -69,8 +66,7 @@ public void socialLogout(final OAuthSocialLogoutRequest oAuthSocialLogoutRequest
}

@Transactional
public ReissueResponse reissue(final ReissueRequest reissueRequest) {
final String refreshTokenValue = reissueRequest.refreshToken();
public ReissueResult reissue(final String refreshTokenValue) {
final RefreshToken refreshToken = findRefreshTokenByValue(refreshTokenValue);
final String providerId = refreshToken.getProviderId();
final UserDetails userDetails = findUserDetailsByProviderId(providerId);
Expand All @@ -79,7 +75,7 @@ public ReissueResponse reissue(final ReissueRequest reissueRequest) {
refreshTokenRepository.delete(refreshToken);
refreshTokenRepository.save(newRefreshToken);

return ReissueResponse.of(accessToken, newRefreshToken);
return ReissueResult.of(accessToken, newRefreshToken);
}

public OAuthReissueResponse socialReissue(final OAuthReissueRequest oAuthReissueRequest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
import java.util.Objects;
import java.util.function.Function;

import static org.kakaoshare.backend.domain.funding.exception.FundingDetailErrorCode.INVALID_CANCEL_AMOUNT;
import static org.kakaoshare.backend.domain.funding.exception.FundingErrorCode.INVALID_ATTRIBUTE_AMOUNT;
import static org.kakaoshare.backend.domain.funding.exception.FundingErrorCode.INVALID_STATUS;
import static org.kakaoshare.backend.domain.member.exception.MemberErrorCode.NOT_FOUND;
Expand Down Expand Up @@ -170,7 +171,7 @@ public PaymentFundingSuccessResponse approveFunding(final String providerId,
final Funding funding = findFundingById(fundingOrderDetail.fundingId());
final Member member = findMemberByProviderId(providerId);
final Long amount = payment.getTotalPrice();
saveOrReflectFundingDetail(payment, funding, member, amount);
saveFundingDetail(payment, funding, member);
funding.increaseAccumulateAmount(amount);

// TODO: 5/10/24 결제 후 목표 금액 달성 시
Expand Down Expand Up @@ -224,12 +225,19 @@ public void cancelFundingDetail(final String providerId,
final PaymentFundingDetailCancelRequest paymentFundingCancelRequest) {
final Long fundingDetailId = paymentFundingCancelRequest.fundingDetailId();
final FundingDetail fundingDetail = findFundingDetailById(fundingDetailId);
final Long amount = paymentFundingCancelRequest.amount();
validateCancelAmount(fundingDetail, amount);
validateAlreadyCanceled(fundingDetail, FundingDetail::canceled);
validateMemberFundingDetail(providerId, fundingDetail);
final Long amount = paymentFundingCancelRequest.amount();
refundFundingDetails(amount, fundingDetail);
}

private void validateCancelAmount(final FundingDetail fundingDetail, final Long amount) {
if (fundingDetail.getAmount() < amount) {
throw new FundingDetailException(INVALID_CANCEL_AMOUNT);
}
}

private Order findOrderByPaymentId(final Long paymentId) {
return orderRepository.findByPaymentId(paymentId)
.orElseThrow(() -> new OrderException(OrderErrorCode.NOT_FOUND));
Expand Down Expand Up @@ -480,11 +488,8 @@ private FundingDetail findFundingDetailById(final Long fundingDetailId) {
.orElseThrow(() -> new FundingDetailException(FundingDetailErrorCode.NOT_FOUND));
}

private void saveOrReflectFundingDetail(final Payment payment, final Funding funding, final Member member, final Long amount) {
fundingDetailRepository.findByFundingAndMember(funding, member)
.ifPresentOrElse(
fundingDetail -> fundingDetail.increaseAmountAndRate(amount),
() -> fundingDetailRepository.save(new FundingDetail(member, funding, payment))
);
private void saveFundingDetail(final Payment payment, final Funding funding, final Member member) {
final FundingDetail fundingDetail = new FundingDetail(member, funding, payment);
fundingDetailRepository.save(fundingDetail);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package org.kakaoshare.backend.domain.product.dto;

import com.querydsl.core.annotations.QueryProjection;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.kakaoshare.backend.domain.product.entity.Product;

@Getter
@EqualsAndHashCode(callSuper = false)
@ToString
public class ProductDto {
protected final Long productId;
protected final String name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(
indexes = {@Index(name = "idx_receipt_option_receipt_id",columnList = "receipt_id",unique = true)}
indexes = {@Index(name = "idx_receipt_option_receipt_id", columnList = "receipt_id", unique = false)}
)
public class ReceiptOption {
public class ReceiptOption extends BaseTimeEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
package org.kakaoshare.backend.logging.config;

import lombok.RequiredArgsConstructor;
import org.kakaoshare.backend.logging.interceptor.LoggingInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class LoggingConfig {
@RequiredArgsConstructor
public class LoggingConfig implements WebMvcConfigurer {
private static final String METRIC_URL_PREFIX = "/actuator";
private static final String FAVICON_URL = "/favicon.ico";

private final LoggingInterceptor loggingInterceptor;

@Bean
@RequestScope
public StopWatch stopWatch() {
return new StopWatch();
}

@Override
public void addInterceptors(final InterceptorRegistry registry) {
registry.addInterceptor(loggingInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(METRIC_URL_PREFIX, FAVICON_URL);
}
}
Loading

0 comments on commit 1e15c0b

Please sign in to comment.