diff --git a/backend/src/main/java/com/isp/backend/domain/receipt/controller/ReceiptController.java b/backend/src/main/java/com/isp/backend/domain/receipt/controller/ReceiptController.java index 91828fac..394f3d18 100644 --- a/backend/src/main/java/com/isp/backend/domain/receipt/controller/ReceiptController.java +++ b/backend/src/main/java/com/isp/backend/domain/receipt/controller/ReceiptController.java @@ -3,12 +3,15 @@ import com.isp.backend.domain.receipt.dto.request.ChangeReceiptOrderRequest; import com.isp.backend.domain.receipt.dto.request.SaveReceiptRequest; import com.isp.backend.domain.receipt.dto.response.ReceiptResponse; +import com.isp.backend.domain.receipt.dto.response.ScheduleListWithReceiptResponse; import com.isp.backend.domain.receipt.dto.response.ScheduleReceiptResponse; import com.isp.backend.domain.receipt.entity.Receipt; import com.isp.backend.domain.receipt.service.ReceiptService; +import com.isp.backend.global.security.CustomUserDetails; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -65,6 +68,15 @@ public ResponseEntity getReceiptDetail(@PathVariable Long recei } + /** 영수증용 일정 리스트 목록 조회 API **/ + @GetMapping("/schedules/list") + public ResponseEntity> getScheduleListWithReceipt(@AuthenticationPrincipal CustomUserDetails userDetails) { + String memberUid = userDetails.getUsername(); + List scheduleListWithReceipts = receiptService.getScheduleListWithReceipt(memberUid); + return ResponseEntity.ok(scheduleListWithReceipts); + } + + /** 영수증 순서 변경 API **/ @PutMapping("/order/{scheduleId}") diff --git a/backend/src/main/java/com/isp/backend/domain/receipt/dto/response/ReceiptListResponse.java b/backend/src/main/java/com/isp/backend/domain/receipt/dto/response/ReceiptListResponse.java index 9614d368..dc838dd4 100644 --- a/backend/src/main/java/com/isp/backend/domain/receipt/dto/response/ReceiptListResponse.java +++ b/backend/src/main/java/com/isp/backend/domain/receipt/dto/response/ReceiptListResponse.java @@ -17,7 +17,7 @@ public class ReceiptListResponse { private String storeType ; - private double price ; // receipt 테이블의 totalPrice + private double price ; private int orderNum ; diff --git a/backend/src/main/java/com/isp/backend/domain/receipt/dto/response/ScheduleListWithReceiptResponse.java b/backend/src/main/java/com/isp/backend/domain/receipt/dto/response/ScheduleListWithReceiptResponse.java new file mode 100644 index 00000000..a64dc3db --- /dev/null +++ b/backend/src/main/java/com/isp/backend/domain/receipt/dto/response/ScheduleListWithReceiptResponse.java @@ -0,0 +1,26 @@ +package com.isp.backend.domain.receipt.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +public class ScheduleListWithReceiptResponse { + + private String scheduleName; + + private String startDate; + + private String endDate; + + private String currencyName; + + private double totalReceiptsPrice ; + + private int receiptCount ; + +} diff --git a/backend/src/main/java/com/isp/backend/domain/receipt/mapper/ReceiptMapper.java b/backend/src/main/java/com/isp/backend/domain/receipt/mapper/ReceiptMapper.java index 33baac10..0aacc123 100644 --- a/backend/src/main/java/com/isp/backend/domain/receipt/mapper/ReceiptMapper.java +++ b/backend/src/main/java/com/isp/backend/domain/receipt/mapper/ReceiptMapper.java @@ -5,6 +5,7 @@ import com.isp.backend.domain.receipt.dto.response.ReceiptDetailResponse; import com.isp.backend.domain.receipt.dto.response.ReceiptListResponse; import com.isp.backend.domain.receipt.dto.response.ReceiptResponse; +import com.isp.backend.domain.receipt.dto.response.ScheduleListWithReceiptResponse; import com.isp.backend.domain.receipt.entity.Receipt; import com.isp.backend.domain.receipt.entity.ReceiptDetail; import com.isp.backend.domain.receipt.entity.StoreType; @@ -86,6 +87,21 @@ public ReceiptDetailResponse toReceiptDetailResponse(ReceiptDetail receiptDetail } + // 영수증 용 일정 리스트 목록 조회 + public ScheduleListWithReceiptResponse toScheduleListWithReceiptResponse(Schedule schedule, double totalReceiptsPrice, int receiptCount) { + String currencyName = schedule.getCountry().getCurrencyName(); + + return new ScheduleListWithReceiptResponse( + schedule.getScheduleName(), + schedule.getStartDate(), + schedule.getEndDate(), + currencyName, + totalReceiptsPrice, + receiptCount + ); + } + + } diff --git a/backend/src/main/java/com/isp/backend/domain/receipt/repository/ReceiptRepository.java b/backend/src/main/java/com/isp/backend/domain/receipt/repository/ReceiptRepository.java index a2d4fe82..da3e18a5 100644 --- a/backend/src/main/java/com/isp/backend/domain/receipt/repository/ReceiptRepository.java +++ b/backend/src/main/java/com/isp/backend/domain/receipt/repository/ReceiptRepository.java @@ -17,4 +17,13 @@ public interface ReceiptRepository extends JpaRepository { List findByScheduleId(Long scheduleId); + // 스케줄 ID에 해당하는 영수증의 totalPrice 합계를 구하는 쿼리 + @Query("SELECT SUM(r.totalPrice) FROM Receipt r WHERE r.schedule.id = :scheduleId") + Double sumTotalPriceByScheduleId(@Param("scheduleId") Long scheduleId); + + // 스케줄 ID에 해당하는 영수증의 개수를 구하는 쿼리 + @Query("SELECT COUNT(r) FROM Receipt r WHERE r.schedule.id = :scheduleId") + int countByScheduleId(@Param("scheduleId") Long scheduleId); + + } diff --git a/backend/src/main/java/com/isp/backend/domain/receipt/service/ReceiptService.java b/backend/src/main/java/com/isp/backend/domain/receipt/service/ReceiptService.java index e42e01de..f634b7c7 100644 --- a/backend/src/main/java/com/isp/backend/domain/receipt/service/ReceiptService.java +++ b/backend/src/main/java/com/isp/backend/domain/receipt/service/ReceiptService.java @@ -1,12 +1,11 @@ package com.isp.backend.domain.receipt.service; +import com.isp.backend.domain.member.entity.Member; +import com.isp.backend.domain.member.repository.MemberRepository; import com.isp.backend.domain.receipt.dto.request.ChangeReceiptOrderRequest; import com.isp.backend.domain.receipt.dto.request.ReceiptDetailRequest; import com.isp.backend.domain.receipt.dto.request.SaveReceiptRequest; -import com.isp.backend.domain.receipt.dto.response.ReceiptDetailResponse; -import com.isp.backend.domain.receipt.dto.response.ReceiptListResponse; -import com.isp.backend.domain.receipt.dto.response.ReceiptResponse; -import com.isp.backend.domain.receipt.dto.response.ScheduleReceiptResponse; +import com.isp.backend.domain.receipt.dto.response.*; import com.isp.backend.domain.receipt.entity.Receipt; import com.isp.backend.domain.receipt.entity.ReceiptDetail; import com.isp.backend.domain.receipt.mapper.ReceiptMapper; @@ -15,6 +14,7 @@ import com.isp.backend.domain.schedule.entity.Schedule; import com.isp.backend.domain.schedule.repository.ScheduleRepository; import com.isp.backend.global.exception.Image.ImageAlreadyExistingException; +import com.isp.backend.global.exception.common.MemberNotFoundException; import com.isp.backend.global.exception.receipt.ReceiptNotFoundException; import com.isp.backend.global.exception.schedule.ScheduleNotFoundException; import com.isp.backend.global.s3.constant.S3BucketDirectory; @@ -24,10 +24,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @@ -36,6 +33,7 @@ public class ReceiptService { private final ReceiptRepository receiptRepository; private final ReceiptDetailRepository receiptDetailRepository; + private final MemberRepository memberRepository; private final ScheduleRepository scheduleRepository; private final ReceiptMapper receiptMapper; private final S3ImageService s3ImageService; @@ -173,6 +171,31 @@ public ReceiptResponse getReceiptDetail(Long receiptId) { + /** 영수증용 일정 리스트 목록 조회 API **/ + @Transactional(readOnly = true) + public List getScheduleListWithReceipt(String uid) { + // 유저 정보 확인 + Member findMember = validateUserCheck(uid); + + // 해당 유저의 모든 일정 불러오기 + List scheduleList = scheduleRepository.findSchedulesByMember(findMember); + + // 일정 리스트를 DTO로 변환 + return scheduleList.stream() + .map(schedule -> { + // sumTotalPriceByScheduleId가 null을 반환하면 0.0을 기본값으로 설정 + double totalReceiptsPrice = Optional.ofNullable(receiptRepository.sumTotalPriceByScheduleId(schedule.getId())) + .orElse(0.0); + int receiptCount = receiptRepository.countByScheduleId(schedule.getId()); + return receiptMapper.toScheduleListWithReceiptResponse(schedule, totalReceiptsPrice, receiptCount); + }) + .collect(Collectors.toList()); + + } + + + + // 영수증 순서 변경 메서드 수정 예정 /** 예외처리 및 정확한 로직 분석 필요 **/ @Transactional @@ -212,6 +235,15 @@ public void changeOrderReceipt(Long scheduleId, List } + + /** 유효한 유저 정보 확인 **/ + private Member validateUserCheck(String uid) { + return memberRepository.findByUid(uid) + .orElseThrow(MemberNotFoundException::new); + } + + + /** 유효한 일정 확인 메소드 **/ private Schedule validateSchedule(Long scheduleId) { Schedule findSchedule = scheduleRepository.findByIdAndActivatedIsTrue(scheduleId)