Skip to content

Commit

Permalink
Merge branch 'develop' into feature/revenue-statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
matrixpower1004 authored Jan 27, 2024
2 parents 4886bac + d0bd24e commit d8d5c26
Show file tree
Hide file tree
Showing 31 changed files with 813 additions and 212 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ private String getMainCouponName(Long accommodationId) {
public AccommodationDetailResponse findAccommodationWithRooms(
Long accommodationId, LocalDate startDate, LocalDate endDate
) {
Accommodation accommodation = findAccommodationById(accommodationId);
Accommodation accommodation = accommodationQueryUseCase.getAccommodationById(
accommodationId);

List<Room> filterRooms = getFilteredRoomsByDate(
accommodation.getRooms(), startDate, endDate
Expand All @@ -216,13 +217,12 @@ room, getDiscountPrice(room),
);
}

private Accommodation findAccommodationById(Long accommodationId) {
Accommodation accommodation =
accommodationRepository.findById(accommodationId)
.orElseThrow(AccommodationNotFoundException::new);
return accommodation;
@Transactional(readOnly = true)
public Accommodation findAccommodationByRoomId(long roomId) {
return roomQueryService.findRoomById(roomId).getAccommodation();
}


private int getDiscountPrice(Room room) {
return couponService.getSortedTotalCouponResponseInRoom(room)
.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ public Accommodation getAccommodationById(long accommodationId) {
.orElseThrow(AccommodationNotFoundException::new);
}

@Override
@Transactional(readOnly = true)
public boolean existsById(Long accommodationId) {
return accommodationRepository.existsById(accommodationId);
}

@Override
public AccommodationOwnership saveOwnership(Member member, Accommodation accommodation) {
return accommodationOwnershipRepository.save(AccommodationOwnership.builder()
Expand All @@ -74,7 +80,7 @@ public boolean existsOwnershipByMemberAndAccommodation(Member member,
@Override
@Transactional(readOnly = true)
public Category getCategoryByName(String name) {
return categoryRepository.findCategoryByName(name)
return categoryRepository.findCategoryByNameAndIdGreaterThan(name, 4L)
.orElseThrow(WrongCategoryException::new);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public interface AccommodationQueryUseCase {

Accommodation getAccommodationById(long id);

boolean existsById(Long accommodationId);

AccommodationOwnership saveOwnership(Member member, Accommodation accommodation);

List<AccommodationOwnership> getOwnershipByMember(Member member);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.backoffice.upjuyanolja.domain.coupon.entity;

import com.backoffice.upjuyanolja.domain.point.entity.PointUsage;
import com.backoffice.upjuyanolja.domain.room.entity.Room;
import com.backoffice.upjuyanolja.global.common.entity.BaseTime;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -40,6 +41,11 @@ public class CouponIssuance extends BaseTime {
@Comment("객실 식별자")
private Room room;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false, name = "point_usage_id")
@Comment("객실 식별자")
private PointUsage pointUsage;

@Column(nullable = false)
@Comment("발급 수량")
private int quantity;
Expand All @@ -53,13 +59,16 @@ public CouponIssuance(
Long id,
Coupon coupon,
Room room,
PointUsage pointUsage,
int quantity,
int amount
) {
this.id = id;
this.coupon = coupon;
this.room = room;
this.pointUsage = pointUsage;
this.quantity = quantity;
this.amount = amount;
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.backoffice.upjuyanolja.domain.coupon.repository;

import com.backoffice.upjuyanolja.domain.coupon.entity.CouponIssuance;
import com.backoffice.upjuyanolja.domain.point.entity.PointUsage;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CouponIssuanceRepository extends JpaRepository<CouponIssuance, Long> {

List<CouponIssuance> findByPointUsage(PointUsage pointUsage);

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import static java.util.stream.Collectors.toList;

import com.backoffice.upjuyanolja.domain.accommodation.exception.AccommodationNotFoundException;
import com.backoffice.upjuyanolja.domain.accommodation.repository.AccommodationRepository;
import com.backoffice.upjuyanolja.domain.accommodation.service.usecase.AccommodationQueryUseCase;
import com.backoffice.upjuyanolja.domain.coupon.dto.request.backoffice.CouponAddInfos;
import com.backoffice.upjuyanolja.domain.coupon.dto.request.backoffice.CouponAddRequest;
import com.backoffice.upjuyanolja.domain.coupon.dto.request.backoffice.CouponDeleteRequest;
Expand All @@ -22,13 +22,11 @@
import com.backoffice.upjuyanolja.domain.coupon.entity.Coupon;
import com.backoffice.upjuyanolja.domain.coupon.entity.CouponIssuance;
import com.backoffice.upjuyanolja.domain.coupon.entity.DiscountType;
import com.backoffice.upjuyanolja.domain.coupon.exception.InsufficientPointsException;
import com.backoffice.upjuyanolja.domain.coupon.exception.InvalidCouponInfoException;
import com.backoffice.upjuyanolja.domain.coupon.repository.CouponIssuanceRepository;
import com.backoffice.upjuyanolja.domain.coupon.repository.CouponRepository;
import com.backoffice.upjuyanolja.domain.point.entity.Point;
import com.backoffice.upjuyanolja.domain.point.exception.PointNotFoundException;
import com.backoffice.upjuyanolja.domain.point.repository.PointRepository;
import com.backoffice.upjuyanolja.domain.point.entity.PointUsage;
import com.backoffice.upjuyanolja.domain.point.service.PointService;
import com.backoffice.upjuyanolja.domain.room.entity.Room;
import com.backoffice.upjuyanolja.domain.room.repository.RoomRepository;
import com.backoffice.upjuyanolja.global.exception.NotOwnerException;
Expand All @@ -49,10 +47,11 @@ public class CouponBackofficeService {

private final CouponRepository couponRepository;
private final RoomRepository roomRepository;
private final PointRepository pointRepository;
private final AccommodationRepository accommodationRepository;
private final CouponIssuanceRepository couponIssuanceRepository;

private final AccommodationQueryUseCase accommodationQueryUseCase;
private final PointService pointService;

// 쿠폰 만들기 View Response
public CouponMakeViewResponse getRoomsByAccommodation(Long accommodationId) {
return couponRepository.findRoomsByAccommodationId(accommodationId);
Expand All @@ -63,7 +62,10 @@ public void createCoupon(
final CouponMakeRequest couponMakeRequest, final Long memberId
) {
final long totalPoints = couponMakeRequest.totalPoints();
Point point = validationPoint(memberId, totalPoints);
pointService.validatePoint(memberId, totalPoints);

// 업주의 보유 포인트 차감
PointUsage pointUsage = pointService.usePointForCoupon(memberId, totalPoints);

List<CouponRoomsRequest> couponRooms = couponMakeRequest.rooms();
List<Coupon> coupons = new ArrayList<>();
Expand Down Expand Up @@ -98,19 +100,14 @@ public void createCoupon(
log.info("신규 쿠폰 발급: {}, memberId: {}", quantity, memberId);
}
// 5. 쿠폰 발급 내역 배열 생성
couponIssuances.add(createCouponIssuance(room, coupon, quantity, amount));
couponIssuances.add(createCouponIssuance(room, coupon, pointUsage, quantity, amount));
}
// 6. 생성된 쿠폰 저장
couponRepository.saveAll(coupons);
// 7. 생성된 쿠폰 발급 내역 저장
couponIssuanceRepository.saveAll(couponIssuances);

// 8. 업주의 보유 포인트 차감
// todo: 도메인이 다른 서비스를 트랜잭션 안에서 호출하는 게 좋은 설계일까 고민해 보기.
point.decreasePointBalance(totalPoints);
pointRepository.save(point);

// 9. 포인트 사용 이력 전달
// 8. 포인트 사용 이력 전달
// Todo: 포인트 사용 내역 Point 도메인에 전달하기
log.info("쿠폰 발급 성공. 금액: {}", totalPoints);
}
Expand Down Expand Up @@ -146,27 +143,39 @@ public CouponManageResponse manageCoupon(final Long accommodationId) {
public void addonCoupon(final CouponAddRequest couponAddRequest, final long memberId) {
// 1. 업주의 보유 포인트 검증
final long totalPoints = couponAddRequest.totalPoints();
Point point = validationPoint(memberId, totalPoints);
pointService.validatePoint(memberId, totalPoints);

// 2. 업주의 보유 포인트 차감
PointUsage pointUsage = pointService.usePointForCoupon(memberId, totalPoints);

List<Coupon> addCoupons = new ArrayList<>();
List<CouponIssuance> addCouponIssuances = new ArrayList<>();

for (var rooms : couponAddRequest.rooms()) {
for (var coupons : rooms.coupons()) {
addCoupons.add(increaseCouponStock(coupons));

Room room = roomRepository.findById(rooms.roomId()).orElseThrow(
InvalidCouponInfoException::new);
Coupon coupon = couponRepository.findById(coupons.couponId()).orElseThrow(
InvalidCouponInfoException::new);
int quantity = coupons.buyQuantity();
int amount = coupons.eachPoint();

addCouponIssuances.add(
(createCouponIssuance(room, coupon, pointUsage, quantity, amount)));
}
}
couponRepository.saveAll(addCoupons);
couponIssuanceRepository.saveAll(addCouponIssuances);

// 2. 업주의 보유 포인트 차감
point.decreasePointBalance(totalPoints);
pointRepository.save(point);

// Todo: 포인트 사용 내역 Point 도메인에 전달하기
log.info("쿠폰 추가 발급 성공. 금액: {}", totalPoints);
}

// 쿠폰 수정
public void modifyCoupon(final CouponModifyRequest modifyRequest) {

List<Coupon> modifyCoupons = new ArrayList<>();
for (var rooms : modifyRequest.rooms()) {
for (var coupons : rooms.coupons()) {
Expand Down Expand Up @@ -245,21 +254,6 @@ private CouponManageRooms createManageRoom(final CouponManageQueryDto dto) {
.build();
}

// 업주의 보유 포인트 검증
@Transactional(readOnly = true)
protected Point validationPoint(final Long memberId, final long totalPoints) {
final Optional<Point> resultPoint = pointRepository.findByMemberId(memberId);
Point point = resultPoint.orElseThrow(PointNotFoundException::new);
final long ownerPoint = point.getTotalPointBalance();

// 쿠폰 구매 요청 금액이 업주의 보유 포인트보다 크다면 예외 발생
if (ownerPoint < totalPoints) {
log.info("업주의 보유 포인트가 부족합니다. 보유 포인트: {}, 요청 포인트: {}",
ownerPoint, totalPoints);
throw new InsufficientPointsException();
}
return point;
}

// 정상적인 숙소 id 요청인지 검증
@Transactional(readOnly = true)
Expand All @@ -272,7 +266,8 @@ public void validateAccommodationRequest(
currentMemberId, accommodationId);
throw new NotOwnerException();
}
if (!accommodationRepository.existsById(accommodationId)) {

if (!accommodationQueryUseCase.existsById(accommodationId)) {
log.info("숙소의 정보를 찾을 수 없습니다. id: {}", accommodationId);
throw new AccommodationNotFoundException();
}
Expand All @@ -286,12 +281,14 @@ private Coupon updateCouponStock(final Coupon coupon, final int quantity) {
private CouponIssuance createCouponIssuance(
final Room room,
final Coupon coupon,
final PointUsage pointUsage,
final int quantity,
final int amount
) {
return CouponIssuance.builder()
.room(room)
.coupon(coupon)
.pointUsage(pointUsage)
.quantity(quantity)
.amount(amount)
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.backoffice.upjuyanolja.domain.coupon.service;

import com.backoffice.upjuyanolja.domain.coupon.entity.CouponIssuance;
import com.backoffice.upjuyanolja.domain.coupon.repository.CouponIssuanceRepository;
import com.backoffice.upjuyanolja.domain.point.entity.PointUsage;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class CouponIssuanceGetService {

private final CouponIssuanceRepository couponIssuanceRepository;

public List<CouponIssuance> getCouponIssuanceByPointUsage(PointUsage pointUsage) {
return couponIssuanceRepository.findByPointUsage(pointUsage);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.backoffice.upjuyanolja.domain.point.dto.response.PointChargeResponse;
import com.backoffice.upjuyanolja.domain.point.dto.response.PointSummaryResponse;
import com.backoffice.upjuyanolja.domain.point.dto.response.PointTotalBalanceResponse;
import com.backoffice.upjuyanolja.domain.point.dto.response.PointTotalPageResponse;
import com.backoffice.upjuyanolja.domain.point.dto.response.PointUsagePageResponse;
import com.backoffice.upjuyanolja.domain.point.service.PointService;
import com.backoffice.upjuyanolja.global.security.SecurityUtil;
import jakarta.validation.Valid;
Expand Down Expand Up @@ -51,9 +53,9 @@ public ResponseEntity<PointSummaryResponse> getPointSummary(
return ResponseEntity.status(HttpStatus.OK).body(response);
}

@GetMapping("/total")
@GetMapping("/total-balance")
public ResponseEntity<PointTotalBalanceResponse> getPointTotalBalance() {
log.info("GET /api/points/total");
log.info("GET /api/points/total-balance");

PointTotalBalanceResponse response = pointService.getPointTotalBalanceResponse(
securityUtil.getCurrentMemberId()
Expand All @@ -68,7 +70,7 @@ public ResponseEntity<PointChargePageResponse> getChargePoints(
) {
log.info("Get /api/points/charges");

PointChargePageResponse response = pointService.getChargePoints(
PointChargePageResponse response = pointService.getPointChargePageResponse(
securityUtil.getCurrentMemberId(), pageable
);

Expand All @@ -81,7 +83,33 @@ public ResponseEntity<PointChargeResponse> getDetailChargePoints(
) {
log.info("Get /api/points/charges/{chargeId}");

PointChargeResponse response = pointService.getDetailChargePoint(chargeId);
PointChargeResponse response = pointService.getDetailChargePointResponse(chargeId);

return ResponseEntity.status(HttpStatus.OK).body(response);
}

@GetMapping("/usages")
public ResponseEntity<PointUsagePageResponse> getUsagePoints(
@PageableDefault(page = 0, size = 4) Pageable pageable
) {
log.info("Get /api/points/usages");

PointUsagePageResponse response = pointService.getPointUsagePageResponse(
securityUtil.getCurrentMemberId(), pageable
);

return ResponseEntity.status(HttpStatus.OK).body(response);
}

@GetMapping("/total")
public ResponseEntity<PointTotalPageResponse> getTotalPoints(
@PageableDefault(page = 0, size = 4) Pageable pageable
) {
log.info("Get /api/points/total");

PointTotalPageResponse response = pointService.getTotalPointPageResponse(
securityUtil.getCurrentMemberId(), pageable
);

return ResponseEntity.status(HttpStatus.OK).body(response);
}
Expand All @@ -92,7 +120,7 @@ public ResponseEntity<PointChargeResponse> chargePoint(
) {
log.info("Post /api/points/charges");

PointChargeResponse response = pointService.getChargePointResponse(
PointChargeResponse response = pointService.chargePoint(
securityUtil.getCurrentMemberId(), request
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.backoffice.upjuyanolja.domain.point.dto.response;

import com.backoffice.upjuyanolja.domain.point.entity.PointCharges;
import java.time.format.DateTimeFormatter;
import lombok.Builder;

@Builder
Expand All @@ -16,7 +17,7 @@ public static PointChargeResponse of(
) {
return PointChargeResponse.builder()
.orderId(pointCharges.getOrderName())
.tradeAt(pointCharges.getChargeDate().toString())
.tradeAt(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(pointCharges.getChargeDate()))
.orderName(pointCharges.getChargePoint()+"원")
.amount(pointCharges.getChargePoint())
.build();
Expand Down
Loading

0 comments on commit d8d5c26

Please sign in to comment.