diff --git a/src/main/java/com/back/domain/dashboard/admin/service/AdminDashboardServiceImpl.java b/src/main/java/com/back/domain/dashboard/admin/service/AdminDashboardServiceImpl.java index c864aa35..146b2f56 100644 --- a/src/main/java/com/back/domain/dashboard/admin/service/AdminDashboardServiceImpl.java +++ b/src/main/java/com/back/domain/dashboard/admin/service/AdminDashboardServiceImpl.java @@ -121,6 +121,7 @@ public AdminOverviewResponse getOverview(AdminOverviewRequest request) { .getContent(); List artistApprovals = pendingApplications.stream() + .filter(app -> app.getUser() != null) // User가 null인 경우 필터링 .map(app -> new AdminOverviewResponse.ArtistApproval( app.getUser().getId(), app.getArtistName(), @@ -137,6 +138,7 @@ public AdminOverviewResponse getOverview(AdminOverviewRequest request) { .getContent(); List fundingApprovals = pendingFundings.stream() + .filter(funding -> funding.getUser() != null) // User가 null인 경우 필터링 .map(funding -> new AdminOverviewResponse.FundingApproval( funding.getId(), funding.getTitle(), @@ -649,6 +651,13 @@ public AdminFundingResponse getFundings(AdminFundingSearchRequest request) { * Funding Entity → DTO 변환 (화면 표시 필드만, 평면 구조) */ private AdminFundingResponse.Funding convertToFundingDto(Funding funding) { + // User null 체크 (FK 제약조건상 발생하면 안되지만 방어적 처리) + if (funding.getUser() == null) { + log.error("Funding의 User가 null입니다 - fundingId: {}", funding.getId()); + throw new ServiceException("DATA_INTEGRITY_ERROR", + "펀딩 데이터 무결성 오류 - fundingId: " + funding.getId()); + } + // 달성률 계산 int achievementRate = funding.getTargetAmount() > 0 ? (int) ((funding.getCollectedAmount() * 100) / funding.getTargetAmount()) @@ -791,6 +800,13 @@ public AdminArtistApplicationResponse getArtistApplications(AdminArtistApplicati * ArtistApplication Entity → DTO 변환 */ private AdminArtistApplicationResponse.Application convertToApplicationDto(ArtistApplication application) { + // User null 체크 (FK 제약조건상 발생하면 안되지만 방어적 처리) + if (application.getUser() == null) { + log.error("ArtistApplication의 User가 null입니다 - applicationId: {}", application.getId()); + throw new ServiceException("DATA_INTEGRITY_ERROR", + "입점 신청 데이터 무결성 오류 - applicationId: " + application.getId()); + } + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); return new AdminArtistApplicationResponse.Application( diff --git a/src/main/java/com/back/domain/dashboard/customer/service/DashboardServiceImpl.java b/src/main/java/com/back/domain/dashboard/customer/service/DashboardServiceImpl.java index 909d6f3e..935bf24a 100644 --- a/src/main/java/com/back/domain/dashboard/customer/service/DashboardServiceImpl.java +++ b/src/main/java/com/back/domain/dashboard/customer/service/DashboardServiceImpl.java @@ -373,6 +373,18 @@ private OrderResponse.Summary convertToOrderSummary(com.back.domain.order.order. */ private OrderResponse.Product convertToProductDto(com.back.domain.order.orderItem.entity.OrderItem orderItem) { com.back.domain.product.product.entity.Product product = orderItem.getProduct(); + + // 상품이 삭제되었거나 null인 경우 처리 + if (product == null) { + log.warn("OrderItem의 Product가 null입니다 - orderItemId: {}", orderItem.getId()); + return new OrderResponse.Product( + null, + "삭제된 상품", + orderItem.getQuantity(), + orderItem.getPrice().intValue(), + null + ); + } return new OrderResponse.Product( product.getId(), @@ -388,6 +400,19 @@ private OrderResponse.Product convertToProductDto(com.back.domain.order.orderIte */ private OrderResponse.OrderItem convertToOrderItemDto(com.back.domain.order.orderItem.entity.OrderItem orderItem) { com.back.domain.product.product.entity.Product product = orderItem.getProduct(); + + // 상품이 삭제되었거나 null인 경우 처리 + if (product == null) { + log.warn("OrderItem의 Product가 null입니다 - orderItemId: {}", orderItem.getId()); + return new OrderResponse.OrderItem( + orderItem.getId(), + null, + "삭제된 상품", + orderItem.getQuantity(), + orderItem.getPrice().intValue(), + null + ); + } return new OrderResponse.OrderItem( orderItem.getId(), diff --git a/src/main/java/com/back/domain/product/product/service/ProductService.java b/src/main/java/com/back/domain/product/product/service/ProductService.java index ba45567c..75a060dc 100644 --- a/src/main/java/com/back/domain/product/product/service/ProductService.java +++ b/src/main/java/com/back/domain/product/product/service/ProductService.java @@ -298,11 +298,6 @@ public ShareLinkResponse generateShareLink(UUID productUuid, String platform, Cu // 베이스 URL 생성 (프론트엔드 URL) String baseUrl = frontendUrl + "/product/" + productUuid; - // UTM 파라미터 생성 - // utm_source: 유입 경로 (instagram, youtube 등) - // utm_medium: 매체 타입 (social 고정) - // utm_campaign: 캠페인 (작가 ID 포함) - // utm_content: 추가 정보 (product_share 고정) String utmParams = String.format( "?utm_source=%s&utm_medium=social&utm_campaign=artist_%d&utm_content=product_share", normalizedPlatform, @@ -319,7 +314,7 @@ public ShareLinkResponse generateShareLink(UUID productUuid, String platform, Cu normalizedPlatform, artistId, productUuid, - product.getName() // 상품명을 설명으로 사용 + product.getName() ); }