diff --git a/build.gradle b/build.gradle index 2e7378c..418ba90 100644 --- a/build.gradle +++ b/build.gradle @@ -44,6 +44,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" + implementation "com.querydsl:querydsl-collections:5.0.0" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" } diff --git a/src/main/java/com/ClubAccount_BE/core/s3/DefaultS3UrlBuilder.java b/src/main/java/com/ClubAccount_BE/core/s3/DefaultS3UrlBuilder.java index 1bbd2c3..c1c65de 100644 --- a/src/main/java/com/ClubAccount_BE/core/s3/DefaultS3UrlBuilder.java +++ b/src/main/java/com/ClubAccount_BE/core/s3/DefaultS3UrlBuilder.java @@ -1,5 +1,8 @@ package com.ClubAccount_BE.core.s3; +import static com.ClubAccount_BE.core.constant.CommonConstant.IMAGE_KEY_DELIMITER; + +import java.util.UUID; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -16,4 +19,9 @@ public class DefaultS3UrlBuilder implements S3UrlBuilder { public String toUrl(String key) { return "https://" + bucket + ".s3." + region + ".amazonaws.com/" + key; } + + @Override + public String createObjectName(String objectName) { + return UUID.randomUUID() + IMAGE_KEY_DELIMITER + objectName; + } } \ No newline at end of file diff --git a/src/main/java/com/ClubAccount_BE/core/s3/S3UrlBuilder.java b/src/main/java/com/ClubAccount_BE/core/s3/S3UrlBuilder.java index b748123..4132505 100644 --- a/src/main/java/com/ClubAccount_BE/core/s3/S3UrlBuilder.java +++ b/src/main/java/com/ClubAccount_BE/core/s3/S3UrlBuilder.java @@ -2,4 +2,6 @@ public interface S3UrlBuilder { String toUrl(String key); + + String createObjectName(String objectName); } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/FindReceiptController.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/FindReceiptController.java index cf698ff..d00d728 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/FindReceiptController.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/FindReceiptController.java @@ -30,13 +30,13 @@ public class FindReceiptController implements FindReceiptApi { private final FindReceiptUseCase findReceiptUseCase; @GetMapping("/{link}/receipts") - public PagingResponse getReceiptList( + public PagingResponse getReceiptsByDate( @PathVariable(value = "link") UUID link, @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate, @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate, @PageableDefault(page = 1, sort = "createdAt", direction = Sort.Direction.ASC) Pageable pageable ) { - return findReceiptUseCase.getReceiptList(link, startDate, endDate, pageable); + return findReceiptUseCase.getReceiptsByDate(link, startDate, endDate, pageable); } @GetMapping("/{link}/receipts/{receiptId}") @@ -47,18 +47,18 @@ public List getReceiptItem( return findReceiptUseCase.getReceiptItem(link, receiptId); } - @GetMapping("/{link}/receipts/category-expense") - public ReceiptCategoryExpenseResponse getReceiptCategoryExpense( - @PathVariable(value = "link") UUID link - ) { - return findReceiptUseCase.getReceiptCategoryExpense(link); - } - @GetMapping("/{link}/receipts/monthly-expense") - public List getReceiptMonthlyExpenseList( + public List getReceiptExpenseByMonth( @PathVariable(value = "link") UUID link, @Positive(message = "유효하지 않은 연도입니다.") @RequestParam int year ) { - return findReceiptUseCase.getReceiptMonthlyExpenseList(link, year); + return findReceiptUseCase.getReceiptExpenseByMonth(link, year); + } + + @GetMapping("/{link}/receipts/category-expense") + public List getReceiptExpenseByCategory( + @PathVariable(value = "link") UUID link + ) { + return findReceiptUseCase.getReceiptExpenseByCategory(link); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/api/FindReceiptApi.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/api/FindReceiptApi.java index f86229e..4b23a42 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/api/FindReceiptApi.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/api/FindReceiptApi.java @@ -24,7 +24,7 @@ public interface FindReceiptApi { @Operation( summary = "영수증 목록 조회", description = "시작일과 종료일을 기준으로 파싱된 영수증을 조회한다. 시작일과 종료일에 정보가 없을 경우 모든 영수증을 조회한다.") - PagingResponse getReceiptList( + PagingResponse getReceiptsByDate( @PathVariable(value = "link") UUID link, @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate, @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate, @@ -37,14 +37,14 @@ List getReceiptItem( @PathVariable("receiptId") Long receiptId ); - @Operation(summary = "영수증 카테고리별 지출 조회", description = "등록된 영수증의 카테고리별 지출을 조회한다.") - ReceiptCategoryExpenseResponse getReceiptCategoryExpense( - @PathVariable(value = "link") UUID link - ); - @Operation(summary = "영수증 월별 지출 목록 조회", description = "등록된 영수증의 월별 지출을 조회한다.") - List getReceiptMonthlyExpenseList( + List getReceiptExpenseByMonth( @PathVariable(value = "link") UUID link, @Positive(message = "유효하지 않은 연도입니다.") @RequestParam int year ); + + @Operation(summary = "영수증 카테고리별 지출 조회", description = "등록된 영수증의 카테고리별 지출을 조회한다.") + List getReceiptExpenseByCategory( + @PathVariable(value = "link") UUID link + ); } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/request/ReceiptRequest.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/request/ReceiptRequest.java index e0fe4fa..d9a8be3 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/request/ReceiptRequest.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/request/ReceiptRequest.java @@ -1,6 +1,6 @@ package com.ClubAccount_BE.receipt.adapter.in.web.dto.request; -import com.ClubAccount_BE.receipt.domain.type.ReceiptCategory; +import com.ClubAccount_BE.receipt.domain.ReceiptCategory; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.DecimalMin; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptCategoryExpenseResponse.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptCategoryExpenseResponse.java index 57e2449..8fb2edc 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptCategoryExpenseResponse.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptCategoryExpenseResponse.java @@ -1,35 +1,24 @@ package com.ClubAccount_BE.receipt.adapter.in.web.dto.response; -import com.ClubAccount_BE.receipt.domain.ReceiptCategoryExpenseResult; +import com.ClubAccount_BE.receipt.domain.CategoryExpenseResult; +import com.ClubAccount_BE.receipt.domain.ReceiptCategory; import io.swagger.v3.oas.annotations.media.Schema; import java.math.BigDecimal; import lombok.Builder; @Builder public record ReceiptCategoryExpenseResponse( - @Schema(description = "회식비 카테고리 총 지출") - BigDecimal groupDiningExpense, + @Schema(description = "영수증 카테고리 종류") + ReceiptCategory category, - @Schema(description = "물품 구매비 카테고리 총 지출") - BigDecimal supplyPurchaseExpense, - - @Schema(description = "정기 구독비 카테고리 총 지출") - BigDecimal subscriptionExpense, - - @Schema(description = "대관비 카테고리 총 지출") - BigDecimal venueRentalExpense, - - @Schema(description = "기타 카테고리 총 지출") - BigDecimal otherExpense + @Schema(description = "해당 카테고리 총 지출 금액") + BigDecimal totalExpense ) { - public static ReceiptCategoryExpenseResponse of(ReceiptCategoryExpenseResult result) { + public static ReceiptCategoryExpenseResponse of(CategoryExpenseResult result) { return ReceiptCategoryExpenseResponse.builder() - .groupDiningExpense(result.getGroupDiningExpense()) - .supplyPurchaseExpense(result.getSupplyPurchaseExpense()) - .subscriptionExpense(result.getSubscriptionExpense()) - .venueRentalExpense(result.getVenueRentalExpense()) - .otherExpense(result.getOtherExpense()) + .category(result.category()) + .totalExpense(result.totalExpense()) .build(); } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptMonthlyExpenseResponse.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptMonthlyExpenseResponse.java index 6dd7016..76d7a06 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptMonthlyExpenseResponse.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptMonthlyExpenseResponse.java @@ -1,6 +1,6 @@ package com.ClubAccount_BE.receipt.adapter.in.web.dto.response; -import com.ClubAccount_BE.receipt.domain.ReceiptMonthlyExpenseResult; +import com.ClubAccount_BE.receipt.domain.MonthlyExpenseResult; import java.math.BigDecimal; import java.util.UUID; import lombok.Builder; @@ -13,12 +13,12 @@ public record ReceiptMonthlyExpenseResponse( BigDecimal totalExpense ) { - public static ReceiptMonthlyExpenseResponse of(ReceiptMonthlyExpenseResult result) { + public static ReceiptMonthlyExpenseResponse of(MonthlyExpenseResult result) { return ReceiptMonthlyExpenseResponse.builder() - .id(UUID.nameUUIDFromBytes((result.getYear() + "-" + result.getMonth()).getBytes())) - .year(result.getYear()) - .month(result.getMonth()) - .totalExpense(result.getTotalExpense()) + .id(UUID.nameUUIDFromBytes((result.year() + "-" + result.month()).getBytes())) + .year(result.year()) + .month(result.month()) + .totalExpense(result.totalExpense()) .build(); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptResponse.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptResponse.java index 05f5398..d5d951b 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptResponse.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/in/web/dto/response/ReceiptResponse.java @@ -1,7 +1,7 @@ package com.ClubAccount_BE.receipt.adapter.in.web.dto.response; import com.ClubAccount_BE.receipt.domain.Receipt; -import com.ClubAccount_BE.receipt.domain.type.ReceiptCategory; +import com.ClubAccount_BE.receipt.domain.ReceiptCategory; import java.math.BigDecimal; import java.time.LocalDate; import lombok.Builder; diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptImageAdapter.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptImageAdapter.java index ef7d68a..1421519 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptImageAdapter.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptImageAdapter.java @@ -4,6 +4,8 @@ import static com.ClubAccount_BE.core.exception.ErrorCode.S3_UPLOAD_FAIL; import com.ClubAccount_BE.core.exception.ApiException; +import com.ClubAccount_BE.core.s3.S3KeyExtractor; +import com.ClubAccount_BE.core.s3.S3UrlBuilder; import com.ClubAccount_BE.receipt.application.port.out.DeleteReceiptImagePort; import com.ClubAccount_BE.receipt.application.port.out.UploadReceiptImagePort; import java.io.IOException; @@ -24,13 +26,15 @@ public class ReceiptImageAdapter implements UploadReceiptImagePort, DeleteReceiptImagePort { private final S3Client amazonS3; + private final S3KeyExtractor keyExtractor; + private final S3UrlBuilder urlBuilder; @Value("${cloud.aws.s3.bucket}") private String bucket; @Override public String uploadReceipt(MultipartFile image) { - String imageName = createImageName(image.getOriginalFilename()); + String imageName = urlBuilder.createObjectName(image.getOriginalFilename()); try { PutObjectRequest putObjectRequest = PutObjectRequest.builder() @@ -38,7 +42,6 @@ public String uploadReceipt(MultipartFile image) { .key(imageName) .contentType(image.getContentType()) .build(); - amazonS3.putObject( putObjectRequest, RequestBody.fromInputStream(image.getInputStream(), image.getSize()) @@ -47,15 +50,13 @@ public String uploadReceipt(MultipartFile image) { } catch (IOException e) { throw new ApiException(S3_UPLOAD_FAIL); } - - return getImageUrl(imageName); + return urlBuilder.toUrl(imageName); } - // TODO: S3에서 이미지 삭제 로직 비동기 처리 @Override public void deleteImages(List receiptImage) { receiptImage.forEach(url -> { - String key = extractKey(url); + String key = keyExtractor.extractKey(url); DeleteObjectRequest request = DeleteObjectRequest.builder() .bucket(bucket) .key(key) @@ -63,18 +64,4 @@ public void deleteImages(List receiptImage) { amazonS3.deleteObject(request); }); } - - private String createImageName(String originalFilename) { - return UUID.randomUUID() + IMAGE_KEY_DELIMITER + originalFilename; - } - - private String getImageUrl(String fileName) { - return amazonS3.utilities() - .getUrl(builder -> builder.bucket(bucket).key(fileName)) - .toExternalForm(); - } - - private String extractKey(String url) { - return URI.create(url).getPath().substring(1); - } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptRepositoryAdapter.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptRepositoryAdapter.java index eac9670..cd56f58 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptRepositoryAdapter.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/ReceiptRepositoryAdapter.java @@ -10,8 +10,10 @@ import com.ClubAccount_BE.receipt.application.port.out.DeleteReceiptPort; import com.ClubAccount_BE.receipt.application.port.out.FindReceiptPort; import com.ClubAccount_BE.receipt.application.port.out.UpdateReceiptPort; +import com.ClubAccount_BE.receipt.domain.CategoryExpenseResult; import com.ClubAccount_BE.receipt.domain.Receipt; import com.ClubAccount_BE.receipt.domain.ReceiptItem; +import com.ClubAccount_BE.receipt.domain.MonthlyExpenseResult; import com.ClubAccount_BE.receipt.mapper.ReceiptItemMapper; import com.ClubAccount_BE.receipt.mapper.ReceiptMapper; import com.ClubAccount_BE.user.domain.User; @@ -24,32 +26,16 @@ @Component @RequiredArgsConstructor -public class ReceiptRepositoryAdapter - implements CreateReceiptPort, FindReceiptPort, UpdateReceiptPort, DeleteReceiptPort { +public class ReceiptRepositoryAdapter implements CreateReceiptPort, FindReceiptPort, UpdateReceiptPort, DeleteReceiptPort { private final ReceiptRepository receiptRepository; @Override - public Long createReceipt(Receipt receipt, List receiptItems) { - ReceiptEntity receiptEntity = ReceiptMapper.toEntity(receipt); - receiptItems.stream() - .map(ReceiptItemMapper::toEntity) - .forEach(receiptEntity::addReceiptItem); - return receiptRepository - .save(receiptEntity) - .getId(); - } - - @Override - public Page getReceiptList( - User user, - LocalDate startDate, - LocalDate endDate, - Pageable pageable - ) { - return receiptRepository - .findAllByDate(user.getId(), startDate, endDate, pageable) - .map(ReceiptMapper::toDomain); + public List getAllReceipts(User user) { + return receiptRepository.findAllByUserId(user.getId()) + .stream() + .map(ReceiptMapper::toDomain) + .toList(); } @Override @@ -61,29 +47,26 @@ public Receipt getReceipt(User user, Long receiptId) { } @Override - public List getReceiptMonthlyExpenseList(User user, int year) { + public Page getReceiptsByDate( + User user, + LocalDate startDate, + LocalDate endDate, + Pageable pageable + ) { return receiptRepository - .findByUserIdAndYear(user.getId(), year) - .stream() - .map(ReceiptMapper::toDomain) - .toList(); - } - - @Override - public List getAllReceipts(User user) { - return receiptRepository.findAllByUserId(user.getId()) - .stream() - .map(ReceiptMapper::toDomain) - .toList(); + .findByDate(user.getId(), startDate, endDate, pageable) + .map(ReceiptMapper::toDomain); } @Override - public List getReceiptCategoryList(User user) { + public Long createReceipt(Receipt receipt, List receiptItems) { + ReceiptEntity receiptEntity = ReceiptMapper.toEntity(receipt); + receiptItems.stream() + .map(ReceiptItemMapper::toEntity) + .forEach(receiptEntity::addReceiptItem); return receiptRepository - .findAllByUserId(user.getId()) - .stream() - .map(ReceiptMapper::toDomain) - .toList(); + .save(receiptEntity) + .getId(); } @Override @@ -103,7 +86,7 @@ public Long updateReceipt( } @Override - public List deleteReceiptList(User user, List receiptIds) { + public List deleteReceipts(User user, List receiptIds) { List receipts = receiptRepository.findAllById(receiptIds); boolean hasInvalidOwner = receipts.stream() @@ -116,4 +99,15 @@ public List deleteReceiptList(User user, List receiptIds) { receiptRepository.deleteAll(receipts); return receipts.stream().map(ReceiptMapper::toDomain).toList(); } + + @Override + public List getReceiptExpenseByMonth(User user, int year) { + return receiptRepository.calculateExpensesByMonth(user.getId(), year); + } + + + @Override + public List getReceiptExpenseByCategory(User user) { + return receiptRepository.calculateExpensesByCategory(user.getId()); + } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/entity/ReceiptEntity.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/entity/ReceiptEntity.java index 58e1b3a..24b6ce8 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/entity/ReceiptEntity.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/entity/ReceiptEntity.java @@ -2,7 +2,7 @@ import com.ClubAccount_BE.core.entity.TimeBaseEntity; import com.ClubAccount_BE.receipt.domain.Receipt; -import com.ClubAccount_BE.receipt.domain.type.ReceiptCategory; +import com.ClubAccount_BE.receipt.domain.ReceiptCategory; import com.ClubAccount_BE.user.adapter.out.persistence.entity.UserEntity; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepository.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepository.java index bdb5283..b00dce1 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepository.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepository.java @@ -1,6 +1,8 @@ package com.ClubAccount_BE.receipt.adapter.out.persistence.repository; import com.ClubAccount_BE.receipt.adapter.out.persistence.entity.ReceiptEntity; +import com.ClubAccount_BE.receipt.domain.CategoryExpenseResult; +import com.ClubAccount_BE.receipt.domain.MonthlyExpenseResult; import java.time.LocalDate; import java.util.List; import org.springframework.data.domain.Page; @@ -8,12 +10,14 @@ public interface ReceiptCustomRepository { - Page findAllByDate( + Page findByDate( Long userId, LocalDate startDate, LocalDate endDate, Pageable pageable ); - List findByUserIdAndYear(Long userId, int year); + List calculateExpensesByMonth(Long userId, int year); + + List calculateExpensesByCategory(Long userId); } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepositoryImpl.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepositoryImpl.java index e7e944d..002e0af 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepositoryImpl.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptCustomRepositoryImpl.java @@ -3,7 +3,11 @@ import static com.ClubAccount_BE.receipt.adapter.out.persistence.entity.QReceiptEntity.receiptEntity; import com.ClubAccount_BE.receipt.adapter.out.persistence.entity.ReceiptEntity; +import com.ClubAccount_BE.receipt.domain.CategoryExpenseResult; +import com.ClubAccount_BE.receipt.domain.MonthlyExpenseResult; import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import java.time.LocalDate; @@ -19,7 +23,7 @@ public class ReceiptCustomRepositoryImpl implements ReceiptCustomRepository { private final JPAQueryFactory queryFactory; @Override - public Page findAllByDate( + public Page findByDate( Long userId, LocalDate startDate, LocalDate endDate, @@ -50,13 +54,33 @@ public Page findAllByDate( } @Override - public List findByUserIdAndYear(Long userId, int year) { + public List calculateExpensesByMonth(Long userId, int year) { return queryFactory - .selectFrom(receiptEntity) + .select(Projections.constructor( + MonthlyExpenseResult.class, + Expressions.constant(year), + receiptEntity.date.month(), + receiptEntity.amount.sum() + )) + .from(receiptEntity) .where( receiptEntity.user.id.eq(userId), receiptEntity.date.year().eq(year) ) + .groupBy(receiptEntity.date.month()) + .fetch(); + } + + @Override + public List calculateExpensesByCategory(Long userId) { + return queryFactory + .select(Projections.constructor(CategoryExpenseResult.class, + receiptEntity.category, + receiptEntity.amount.sum() + )) + .from(receiptEntity) + .where(receiptEntity.user.id.eq(userId)) + .groupBy(receiptEntity.category) .fetch(); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptRepository.java b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptRepository.java index 08d349a..9aa83e3 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptRepository.java +++ b/src/main/java/com/ClubAccount_BE/receipt/adapter/out/persistence/repository/ReceiptRepository.java @@ -6,8 +6,7 @@ import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; -public interface ReceiptRepository extends JpaRepository, - ReceiptCustomRepository { +public interface ReceiptRepository extends JpaRepository, ReceiptCustomRepository { List findAllByUserId(Long id); diff --git a/src/main/java/com/ClubAccount_BE/receipt/application/port/in/FindReceiptUseCase.java b/src/main/java/com/ClubAccount_BE/receipt/application/port/in/FindReceiptUseCase.java index 9bbc130..7fa30c6 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/application/port/in/FindReceiptUseCase.java +++ b/src/main/java/com/ClubAccount_BE/receipt/application/port/in/FindReceiptUseCase.java @@ -12,9 +12,8 @@ public interface FindReceiptUseCase { - ReceiptCategoryExpenseResponse getReceiptCategoryExpense(UUID link); - PagingResponse getReceiptList( + PagingResponse getReceiptsByDate( UUID link, LocalDate startDate, LocalDate endDate, @@ -23,5 +22,7 @@ PagingResponse getReceiptList( List getReceiptItem(UUID link, Long receiptId); - List getReceiptMonthlyExpenseList(UUID link, int year); + List getReceiptExpenseByMonth(UUID link, int year); + + List getReceiptExpenseByCategory(UUID link); } diff --git a/src/main/java/com/ClubAccount_BE/receipt/application/port/out/DeleteReceiptPort.java b/src/main/java/com/ClubAccount_BE/receipt/application/port/out/DeleteReceiptPort.java index 4b0448d..212f1ba 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/application/port/out/DeleteReceiptPort.java +++ b/src/main/java/com/ClubAccount_BE/receipt/application/port/out/DeleteReceiptPort.java @@ -6,5 +6,5 @@ public interface DeleteReceiptPort { - List deleteReceiptList(User user, List receiptIds); + List deleteReceipts(User user, List receiptIds); } diff --git a/src/main/java/com/ClubAccount_BE/receipt/application/port/out/FindReceiptPort.java b/src/main/java/com/ClubAccount_BE/receipt/application/port/out/FindReceiptPort.java index bd7c79c..9a603c7 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/application/port/out/FindReceiptPort.java +++ b/src/main/java/com/ClubAccount_BE/receipt/application/port/out/FindReceiptPort.java @@ -1,6 +1,8 @@ package com.ClubAccount_BE.receipt.application.port.out; +import com.ClubAccount_BE.receipt.domain.CategoryExpenseResult; import com.ClubAccount_BE.receipt.domain.Receipt; +import com.ClubAccount_BE.receipt.domain.MonthlyExpenseResult; import com.ClubAccount_BE.user.domain.User; import java.time.LocalDate; import java.util.List; @@ -9,18 +11,18 @@ public interface FindReceiptPort { - Page getReceiptList( + List getAllReceipts(User user); + + Receipt getReceipt(User user, Long receiptId); + + Page getReceiptsByDate( User user, LocalDate startDate, LocalDate endDate, Pageable pageable ); - List getReceiptCategoryList(User user); + List getReceiptExpenseByMonth(User user, int year); - Receipt getReceipt(User user, Long receiptId); - - List getReceiptMonthlyExpenseList(User user, int year); - - List getAllReceipts(User user); + List getReceiptExpenseByCategory(User user); } diff --git a/src/main/java/com/ClubAccount_BE/receipt/application/service/CreateReceiptService.java b/src/main/java/com/ClubAccount_BE/receipt/application/service/CreateReceiptService.java index e6e29bd..06a8f14 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/application/service/CreateReceiptService.java +++ b/src/main/java/com/ClubAccount_BE/receipt/application/service/CreateReceiptService.java @@ -8,8 +8,7 @@ import com.ClubAccount_BE.receipt.application.port.out.UploadReceiptImagePort; import com.ClubAccount_BE.receipt.domain.Receipt; import com.ClubAccount_BE.receipt.domain.ReceiptItem; -import com.ClubAccount_BE.receipt.domain.service.ReceiptEditor; -import com.ClubAccount_BE.receipt.domain.service.ReceiptItemEditor; +import com.ClubAccount_BE.receipt.mapper.ReceiptItemMapper; import com.ClubAccount_BE.user.domain.User; import java.util.List; import lombok.RequiredArgsConstructor; @@ -24,8 +23,6 @@ public class CreateReceiptService implements CreateReceiptUseCase { private final CreateReceiptPort createReceiptPort; private final UploadReceiptImagePort uploadReceiptImagePort; - private final ReceiptEditor receiptEditor; - private final ReceiptItemEditor receiptItemEditor; @Override public Long createReceipt( @@ -42,9 +39,9 @@ public Long createReceipt( receiptRequest.etc(), image == null ? DEFAULT_IMAGE : uploadReceiptImagePort.uploadReceipt(image) ); - List receiptItems = receiptItemEditor.toReceiptItems(receiptRequest, receipt); - boolean isAmountMatched = receiptEditor.checkAmountMatch(receipt, receiptItems); - receipt.updateAmountMatched(isAmountMatched); + + List receiptItems = ReceiptItemMapper.toReceiptItems(receipt, receiptRequest.receiptItems()); + receipt.updateAmountMatched(receiptItems); return createReceiptPort.createReceipt(receipt, receiptItems); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/application/service/DeleteReceiptService.java b/src/main/java/com/ClubAccount_BE/receipt/application/service/DeleteReceiptService.java index 9ebefee..e6d9ffc 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/application/service/DeleteReceiptService.java +++ b/src/main/java/com/ClubAccount_BE/receipt/application/service/DeleteReceiptService.java @@ -1,10 +1,11 @@ package com.ClubAccount_BE.receipt.application.service; +import static com.ClubAccount_BE.core.constant.CommonConstant.DEFAULT_IMAGE; + import com.ClubAccount_BE.receipt.application.port.in.DeleteReceiptUseCase; import com.ClubAccount_BE.receipt.application.port.out.DeleteReceiptImagePort; import com.ClubAccount_BE.receipt.application.port.out.DeleteReceiptPort; import com.ClubAccount_BE.receipt.domain.Receipt; -import com.ClubAccount_BE.receipt.domain.service.ReceiptEditor; import com.ClubAccount_BE.user.domain.User; import java.util.List; import lombok.RequiredArgsConstructor; @@ -18,12 +19,14 @@ public class DeleteReceiptService implements DeleteReceiptUseCase { private final DeleteReceiptPort deleteReceiptPort; private final DeleteReceiptImagePort deleteReceiptImagePort; - private final ReceiptEditor receiptEditor; @Override public void deleteReceiptList(User user, List receiptIds) { - List receiptList = deleteReceiptPort.deleteReceiptList(user, receiptIds); - List receiptImage = receiptEditor.deleteReceiptImage(receiptList); + List receiptList = deleteReceiptPort.deleteReceipts(user, receiptIds); + List receiptImage = receiptList.stream() + .filter(receipt -> receipt.isDefaultImage(DEFAULT_IMAGE)) + .map(Receipt::getReceiptImageUrl) + .toList(); deleteReceiptImagePort.deleteImages(receiptImage); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/application/service/FindReceiptService.java b/src/main/java/com/ClubAccount_BE/receipt/application/service/FindReceiptService.java index 7428c48..ea4a4bd 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/application/service/FindReceiptService.java +++ b/src/main/java/com/ClubAccount_BE/receipt/application/service/FindReceiptService.java @@ -11,9 +11,8 @@ import com.ClubAccount_BE.receipt.application.port.in.FindReceiptUseCase; import com.ClubAccount_BE.receipt.application.port.out.FindReceiptPort; import com.ClubAccount_BE.receipt.domain.Receipt; -import com.ClubAccount_BE.receipt.domain.ReceiptCategoryExpenseResult; -import com.ClubAccount_BE.receipt.domain.ReceiptMonthlyExpenseResult; -import com.ClubAccount_BE.receipt.domain.service.ReceiptEditor; +import com.ClubAccount_BE.receipt.domain.CategoryExpenseResult; +import com.ClubAccount_BE.receipt.domain.MonthlyExpenseResult; import com.ClubAccount_BE.user.application.port.out.FindUserPort; import com.ClubAccount_BE.user.domain.User; import java.time.LocalDate; @@ -32,37 +31,9 @@ public class FindReceiptService implements FindReceiptUseCase { private final FindReceiptPort findReceiptPort; private final FindUserPort findUserPort; - private final ReceiptEditor receiptEditor; @Override - public List getReceiptItem(UUID link, Long receiptId) { - - User user = findUserPort.getUserByLink(link); - Receipt receipt = findReceiptPort.getReceipt(user, receiptId); - return receipt.getReceiptItems() - .stream() - .map(ReceiptItemResponse::of) - .toList(); - } - - @Override - public List getReceiptMonthlyExpenseList(UUID link, int year) { - - User user = findUserPort.getUserByLink(link); - List receiptList = findReceiptPort.getReceiptMonthlyExpenseList(user, year); - List results = receiptEditor.calculateMonthlyExpense( - receiptList, - year - ); - - return results.stream() - .map(ReceiptMonthlyExpenseResponse::of) - .toList(); - } - - - @Override - public PagingResponse getReceiptList( + public PagingResponse getReceiptsByDate( UUID link, LocalDate startDate, LocalDate endDate, @@ -74,18 +45,38 @@ public PagingResponse getReceiptList( User user = findUserPort.getUserByLink(link); Page page = findReceiptPort - .getReceiptList(user, startDate, endDate, pageable) + .getReceiptsByDate(user, startDate, endDate, pageable) .map(ReceiptResponse::of); return PagingResponse.of(page); } @Override - public ReceiptCategoryExpenseResponse getReceiptCategoryExpense(UUID link) { + public List getReceiptItem(UUID link, Long receiptId) { + User user = findUserPort.getUserByLink(link); + Receipt receipt = findReceiptPort.getReceipt(user, receiptId); + return receipt.getReceiptItems() + .stream() + .map(ReceiptItemResponse::of) + .toList(); + } + + @Override + public List getReceiptExpenseByMonth(UUID link, int year) { + User user = findUserPort.getUserByLink(link); + List result = findReceiptPort.getReceiptExpenseByMonth(user, year); + return result.stream() + .map(ReceiptMonthlyExpenseResponse::of) + .toList(); + } + + @Override + public List getReceiptExpenseByCategory(UUID link) { User user = findUserPort.getUserByLink(link); - List receiptList = findReceiptPort.getReceiptCategoryList(user); - ReceiptCategoryExpenseResult result = receiptEditor.calculateCategoryExpense(receiptList); - return ReceiptCategoryExpenseResponse.of(result); + List result = findReceiptPort.getReceiptExpenseByCategory(user); + return result.stream() + .map(ReceiptCategoryExpenseResponse::of) + .toList(); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/application/service/UpdateReceiptService.java b/src/main/java/com/ClubAccount_BE/receipt/application/service/UpdateReceiptService.java index e0420fe..2342bc2 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/application/service/UpdateReceiptService.java +++ b/src/main/java/com/ClubAccount_BE/receipt/application/service/UpdateReceiptService.java @@ -5,8 +5,7 @@ import com.ClubAccount_BE.receipt.application.port.out.UpdateReceiptPort; import com.ClubAccount_BE.receipt.domain.Receipt; import com.ClubAccount_BE.receipt.domain.ReceiptItem; -import com.ClubAccount_BE.receipt.domain.service.ReceiptEditor; -import com.ClubAccount_BE.receipt.domain.service.ReceiptItemEditor; +import com.ClubAccount_BE.receipt.mapper.ReceiptItemMapper; import com.ClubAccount_BE.user.domain.User; import java.util.List; import lombok.RequiredArgsConstructor; @@ -19,8 +18,6 @@ public class UpdateReceiptService implements UpdateReceiptUseCase { private final UpdateReceiptPort updateReceiptPort; - private final ReceiptEditor receiptEditor; - private final ReceiptItemEditor receiptItemEditor; @Override public Long updateReceipt( @@ -38,9 +35,8 @@ public Long updateReceipt( receiptRequest.etc() ); - List receiptItems = receiptItemEditor.toReceiptItems(receiptRequest, receipt); - boolean isAmountMatched = receiptEditor.checkAmountMatch(receipt, receiptItems); - receipt.updateAmountMatched(isAmountMatched); + List receiptItems = ReceiptItemMapper.toReceiptItems(receipt, receiptRequest.receiptItems()); + receipt.updateAmountMatched(receiptItems); return updateReceiptPort.updateReceipt(receiptId, receipt, receiptItems); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/CategoryExpenseResult.java b/src/main/java/com/ClubAccount_BE/receipt/domain/CategoryExpenseResult.java new file mode 100644 index 0000000..0da43f3 --- /dev/null +++ b/src/main/java/com/ClubAccount_BE/receipt/domain/CategoryExpenseResult.java @@ -0,0 +1,11 @@ +package com.ClubAccount_BE.receipt.domain; + +import java.math.BigDecimal; +import lombok.Getter; + +public record CategoryExpenseResult( + ReceiptCategory category, + BigDecimal totalExpense +) { + +} diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/MonthlyExpenseResult.java b/src/main/java/com/ClubAccount_BE/receipt/domain/MonthlyExpenseResult.java new file mode 100644 index 0000000..55dd8f7 --- /dev/null +++ b/src/main/java/com/ClubAccount_BE/receipt/domain/MonthlyExpenseResult.java @@ -0,0 +1,12 @@ +package com.ClubAccount_BE.receipt.domain; + +import java.math.BigDecimal; +import lombok.Getter; + +public record MonthlyExpenseResult( + int year, + int month, + BigDecimal totalExpense +) { + +} diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/Receipt.java b/src/main/java/com/ClubAccount_BE/receipt/domain/Receipt.java index cb7bcf0..fb308b4 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/domain/Receipt.java +++ b/src/main/java/com/ClubAccount_BE/receipt/domain/Receipt.java @@ -1,6 +1,5 @@ package com.ClubAccount_BE.receipt.domain; -import com.ClubAccount_BE.receipt.domain.type.ReceiptCategory; import com.ClubAccount_BE.user.domain.User; import java.math.BigDecimal; import java.time.LocalDate; @@ -87,7 +86,15 @@ public static Receipt update( .build(); } - public void updateAmountMatched(boolean amountMatched) { - this.amountMatched = amountMatched; + public void updateAmountMatched(List items) { + BigDecimal total = items.stream() + .map(ReceiptItem::getTotalPrice) + .reduce(BigDecimal.ZERO, BigDecimal::add); + + this.amountMatched = total.compareTo(this.getAmount()) == 0; + } + + public boolean isDefaultImage(String defaultImage) { + return this.receiptImageUrl != null && !this.receiptImageUrl.equals(defaultImage); } } diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/type/ReceiptCategory.java b/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptCategory.java similarity index 88% rename from src/main/java/com/ClubAccount_BE/receipt/domain/type/ReceiptCategory.java rename to src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptCategory.java index 36c1a6c..832b818 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/domain/type/ReceiptCategory.java +++ b/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptCategory.java @@ -1,4 +1,4 @@ -package com.ClubAccount_BE.receipt.domain.type; +package com.ClubAccount_BE.receipt.domain; import lombok.Getter; diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptCategoryExpenseResult.java b/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptCategoryExpenseResult.java deleted file mode 100644 index 2b734ae..0000000 --- a/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptCategoryExpenseResult.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.ClubAccount_BE.receipt.domain; - -import java.math.BigDecimal; -import lombok.Builder; -import lombok.Getter; - -//TODO 도메인 로직 변경 예정에 따른 수정 계획 중.. -@Getter -public class ReceiptCategoryExpenseResult { - - private final BigDecimal groupDiningExpense; - private final BigDecimal supplyPurchaseExpense; - private final BigDecimal subscriptionExpense; - private final BigDecimal venueRentalExpense; - private final BigDecimal otherExpense; - - @Builder - private ReceiptCategoryExpenseResult( - BigDecimal groupDiningExpense, - BigDecimal supplyPurchaseExpense, - BigDecimal subscriptionExpense, - BigDecimal venueRentalExpense, - BigDecimal otherExpense - ) { - this.groupDiningExpense = groupDiningExpense; - this.supplyPurchaseExpense = supplyPurchaseExpense; - this.subscriptionExpense = subscriptionExpense; - this.venueRentalExpense = venueRentalExpense; - this.otherExpense = otherExpense; - } - - public static ReceiptCategoryExpenseResult of( - BigDecimal groupDiningExpense, - BigDecimal supplyPurchaseExpense, - BigDecimal subscriptionExpense, - BigDecimal venueRentalExpense, - BigDecimal otherExpense - ) { - return ReceiptCategoryExpenseResult.builder() - .groupDiningExpense(groupDiningExpense) - .supplyPurchaseExpense(supplyPurchaseExpense) - .subscriptionExpense(subscriptionExpense) - .venueRentalExpense(venueRentalExpense) - .otherExpense(otherExpense) - .build(); - } -} diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptMonthlyExpenseResult.java b/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptMonthlyExpenseResult.java deleted file mode 100644 index 5c8f5a9..0000000 --- a/src/main/java/com/ClubAccount_BE/receipt/domain/ReceiptMonthlyExpenseResult.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.ClubAccount_BE.receipt.domain; - -import java.math.BigDecimal; -import lombok.Builder; -import lombok.Getter; - -//TODO 도메인 로직 변경 예정에 따른 수정 계획 중.. -@Getter -public class ReceiptMonthlyExpenseResult { - - private final int year; - private final int month; - private final BigDecimal totalExpense; - - @Builder - private ReceiptMonthlyExpenseResult(int year, int month, BigDecimal totalExpense) { - this.year = year; - this.month = month; - this.totalExpense = totalExpense; - } - - public static ReceiptMonthlyExpenseResult of(int year, int month, BigDecimal totalExpense) { - return ReceiptMonthlyExpenseResult.builder() - .year(year) - .month(month) - .totalExpense(totalExpense) - .build(); - } -} diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/service/ReceiptEditor.java b/src/main/java/com/ClubAccount_BE/receipt/domain/service/ReceiptEditor.java deleted file mode 100644 index 330261a..0000000 --- a/src/main/java/com/ClubAccount_BE/receipt/domain/service/ReceiptEditor.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.ClubAccount_BE.receipt.domain.service; - -import static com.ClubAccount_BE.core.constant.CommonConstant.DEFAULT_IMAGE; -import static com.ClubAccount_BE.receipt.domain.type.ReceiptCategory.GROUP_DINING; -import static com.ClubAccount_BE.receipt.domain.type.ReceiptCategory.OTHER; -import static com.ClubAccount_BE.receipt.domain.type.ReceiptCategory.SUBSCRIPTION; -import static com.ClubAccount_BE.receipt.domain.type.ReceiptCategory.SUPPLY_PURCHASE; -import static com.ClubAccount_BE.receipt.domain.type.ReceiptCategory.VENUE_RENTAL; - -import com.ClubAccount_BE.receipt.domain.Receipt; -import com.ClubAccount_BE.receipt.domain.ReceiptCategoryExpenseResult; -import com.ClubAccount_BE.receipt.domain.ReceiptItem; -import com.ClubAccount_BE.receipt.domain.ReceiptMonthlyExpenseResult; -import com.ClubAccount_BE.receipt.domain.type.ReceiptCategory; -import java.math.BigDecimal; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.springframework.stereotype.Service; - -@Service -public class ReceiptEditor { - - /** - * 영수증 금액과 영수증 아이템 금액 비교 - */ - public boolean checkAmountMatch(Receipt receipt, List items) { - BigDecimal total = items.stream() - .map(ReceiptItem::getTotalPrice) - .reduce(BigDecimal.ZERO, BigDecimal::add); - - return total.compareTo(receipt.getAmount()) == 0; - } - - /** - * 영수증 카테고리별 지출 계산 - */ - public ReceiptCategoryExpenseResult calculateCategoryExpense(List receipts) { - - Map categoryExpense = receipts.stream() - .collect(Collectors.groupingBy( - Receipt::getCategory, - Collectors.reducing(BigDecimal.ZERO, Receipt::getAmount, BigDecimal::add) - )); - - return ReceiptCategoryExpenseResult.of( - categoryExpense.getOrDefault(GROUP_DINING, BigDecimal.ZERO), - categoryExpense.getOrDefault(SUPPLY_PURCHASE, BigDecimal.ZERO), - categoryExpense.getOrDefault(SUBSCRIPTION, BigDecimal.ZERO), - categoryExpense.getOrDefault(VENUE_RENTAL, BigDecimal.ZERO), - categoryExpense.getOrDefault(OTHER, BigDecimal.ZERO) - ); - } - - /** - * 영수증 월별 지출 계산 - */ - public List calculateMonthlyExpense( - List receiptList, - int year - ) { - Map monthlyExpense = receiptList.stream() - .collect(Collectors.groupingBy( - receipt -> receipt.getDate().getMonthValue(), - Collectors.reducing(BigDecimal.ZERO, Receipt::getAmount, BigDecimal::add) - )); - - return IntStream.rangeClosed(1, 12) - .mapToObj(month -> ReceiptMonthlyExpenseResult.of( - year, - month, - monthlyExpense.getOrDefault(month, BigDecimal.ZERO))) - .collect(Collectors.toList()); - } - - /** - * 영수증 이미지 삭제 시 필요한 URL 리스트 생성 - */ - public List deleteReceiptImage(List receiptList) { - return receiptList.stream() - .map(Receipt::getReceiptImageUrl) - .filter(url -> url != null && !url.equals(DEFAULT_IMAGE)) - .toList(); - } -} diff --git a/src/main/java/com/ClubAccount_BE/receipt/domain/service/ReceiptItemEditor.java b/src/main/java/com/ClubAccount_BE/receipt/domain/service/ReceiptItemEditor.java deleted file mode 100644 index 94616b9..0000000 --- a/src/main/java/com/ClubAccount_BE/receipt/domain/service/ReceiptItemEditor.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.ClubAccount_BE.receipt.domain.service; - -import com.ClubAccount_BE.receipt.adapter.in.web.dto.request.ReceiptRequest; -import com.ClubAccount_BE.receipt.domain.Receipt; -import com.ClubAccount_BE.receipt.domain.ReceiptItem; -import java.util.List; -import org.springframework.stereotype.Service; - -@Service -public class ReceiptItemEditor { - - public List toReceiptItems( - ReceiptRequest receiptRequest, - Receipt receipt - ) { - return receiptRequest.receiptItems().stream() - .map(receiptItem -> ReceiptItem.of( - receipt, - receiptItem.name(), - receiptItem.price(), - receiptItem.totalPrice(), - receiptItem.quantity() - )) - .toList(); - } - -} diff --git a/src/main/java/com/ClubAccount_BE/receipt/mapper/ReceiptItemMapper.java b/src/main/java/com/ClubAccount_BE/receipt/mapper/ReceiptItemMapper.java index 35b6139..06be8f9 100644 --- a/src/main/java/com/ClubAccount_BE/receipt/mapper/ReceiptItemMapper.java +++ b/src/main/java/com/ClubAccount_BE/receipt/mapper/ReceiptItemMapper.java @@ -1,7 +1,10 @@ package com.ClubAccount_BE.receipt.mapper; +import com.ClubAccount_BE.receipt.adapter.in.web.dto.request.ReceiptItemRequest; import com.ClubAccount_BE.receipt.adapter.out.persistence.entity.ReceiptItemEntity; +import com.ClubAccount_BE.receipt.domain.Receipt; import com.ClubAccount_BE.receipt.domain.ReceiptItem; +import java.util.List; public class ReceiptItemMapper { @@ -25,4 +28,16 @@ public static ReceiptItem toDomain(ReceiptItemEntity receiptItemEntity) { .quantity(receiptItemEntity.getQuantity()) .build(); } + + public static List toReceiptItems(Receipt receipt, List requests) { + return requests.stream() + .map(item -> ReceiptItem.of( + receipt, + item.name(), + item.price(), + item.totalPrice(), + item.quantity() + )) + .toList(); + } } diff --git a/src/main/java/com/ClubAccount_BE/user/adapter/out/persistence/ProfileImageAdapter.java b/src/main/java/com/ClubAccount_BE/user/adapter/out/persistence/ProfileImageAdapter.java index 7e6f68d..f373a28 100644 --- a/src/main/java/com/ClubAccount_BE/user/adapter/out/persistence/ProfileImageAdapter.java +++ b/src/main/java/com/ClubAccount_BE/user/adapter/out/persistence/ProfileImageAdapter.java @@ -32,7 +32,7 @@ public class ProfileImageAdapter implements UploadProfileImagePort, DeleteProfil @Override public String uploadProfileImage(Long userId, MultipartFile image) { - String imageName = createImageName(image.getOriginalFilename()); + String imageName = urlBuilder.createObjectName(image.getOriginalFilename()); try { PutObjectRequest request = PutObjectRequest.builder() .bucket(bucket) @@ -48,10 +48,6 @@ public String uploadProfileImage(Long userId, MultipartFile image) { return urlBuilder.toUrl(imageName); } - private String createImageName(String originalFilename) { - return UUID.randomUUID() + IMAGE_KEY_DELIMITER + originalFilename; - } - @Override public void deleteImages(String profileImage) { try { diff --git a/src/test/java/com/ClubAccount_BE/factory/receipt/ReceiptTestFactory.java b/src/test/java/com/ClubAccount_BE/factory/receipt/ReceiptTestFactory.java index bd88e2c..89c9a66 100644 --- a/src/test/java/com/ClubAccount_BE/factory/receipt/ReceiptTestFactory.java +++ b/src/test/java/com/ClubAccount_BE/factory/receipt/ReceiptTestFactory.java @@ -1,7 +1,7 @@ package com.ClubAccount_BE.factory.receipt; import com.ClubAccount_BE.receipt.domain.Receipt; -import com.ClubAccount_BE.receipt.domain.type.ReceiptCategory; +import com.ClubAccount_BE.receipt.domain.ReceiptCategory; import com.ClubAccount_BE.user.domain.User; import java.math.BigDecimal; import java.time.LocalDate;