Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,4 @@ public ApiResponse<PageResponseDto<ProductRegisterHistoryDto>> getRegisterHistor
return ApiResponse.onSuccess(productService.getRegisterHistory(user, pageable));
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.DecodEat.global.common.BaseEntity;
import jakarta.persistence.*;
import lombok.*;
import lombok.experimental.SuperBuilder;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -12,9 +13,9 @@
@Table(name = "product")
@Getter
@Setter
@NoArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@SuperBuilder
public class Product extends BaseEntity {

@Id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.DecodEat.domain.report.controller;

import com.DecodEat.domain.products.dto.response.ProductDetailDto;
import com.DecodEat.domain.report.dto.request.ProductNutritionUpdateRequestDto;
import com.DecodEat.domain.report.dto.response.ReportResponseDto;
import com.DecodEat.domain.report.service.ReportService;
import com.DecodEat.domain.users.entity.User;
import com.DecodEat.global.apiPayload.ApiResponse;
import com.DecodEat.global.common.annotation.CurrentUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/reports")
@Tag(name = "신고")
public class ReportController {

private final ReportService reportService;

@Operation(
summary = "상품 정보 업데이트 요청",
description = "사이트의 영양정보가 실제와 다른 경우 수정 요청")
@PostMapping("/nutrition-info")
public ApiResponse<ReportResponseDto> requestUpdateNutritionInfo(@CurrentUser User user,
@RequestParam Long productId,
@RequestBody ProductNutritionUpdateRequestDto requestDto) {

return ApiResponse.onSuccess(reportService.requestUpdateNutrition(user, productId, requestDto));
}

@Operation(
summary = "상품 사진 확인 요청",
description = "부적절한 이미지인 경우 확인 요청")
@PostMapping("/image")
public ApiResponse<ReportResponseDto> requestCheckImage(@CurrentUser User user,
@RequestParam Long productId,
@RequestParam String imageUrl) {

return ApiResponse.onSuccess(reportService.requestCheckImage(user, productId, imageUrl));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.DecodEat.domain.report.converter;

import com.DecodEat.domain.products.entity.Product;
import com.DecodEat.domain.report.dto.request.ProductNutritionUpdateRequestDto;
import com.DecodEat.domain.report.dto.response.ReportResponseDto;
import com.DecodEat.domain.report.entity.ImageReport;
import com.DecodEat.domain.report.entity.NutritionReport;
import com.DecodEat.domain.report.entity.ReportStatus;
import com.DecodEat.domain.users.entity.User;

public class ReportConverter {
public static ReportResponseDto toReportResponseDto(Long productId, String type){
return ReportResponseDto.builder()
.productId(productId)
.reportContent(type)
.build();
}

public static NutritionReport toNutritionReport(Long reporterId, Product product,ProductNutritionUpdateRequestDto requestDto){
return NutritionReport.builder()
.product(product)
.reporterId(reporterId)
.reportStatus(ReportStatus.IN_PROGRESS)
.calcium(requestDto.getCalcium())
.carbohydrate(requestDto.getCarbohydrate())
.cholesterol(requestDto.getCholesterol())
.dietaryFiber(requestDto.getDietaryFiber())
.energy(requestDto.getEnergy())
.fat(requestDto.getFat())
.protein(requestDto.getProtein())
.satFat(requestDto.getSatFat())
.sodium(requestDto.getSodium())
.sugar(requestDto.getSugar())
.transFat(requestDto.getTransFat())
.build();
}

public static ImageReport toImageReport(Long reporterId, Product product, String imageUrl){
return ImageReport.builder()
.product(product)
.reporterId(reporterId)
.reportStatus(ReportStatus.IN_PROGRESS)
.imageUrl(imageUrl)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.DecodEat.domain.report.dto.request;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class ProductNutritionUpdateRequestDto {
@NotNull(message = "칼슘 정보는 필수입니다.")
@PositiveOrZero(message = "칼슘은 0 이상의 값이어야 합니다.")
private Double calcium;

@NotNull(message = "탄수화물 정보는 필수입니다.")
@PositiveOrZero(message = "탄수화물은 0 이상의 값이어야 합니다.")
private Double carbohydrate;

@NotNull(message = "콜레스테롤 정보는 필수입니다.")
@PositiveOrZero(message = "콜레스테롤은 0 이상의 값이어야 합니다.")
private Double cholesterol;

@NotNull(message = "식이섬유 정보는 필수입니다.")
@PositiveOrZero(message = "식이섬유는 0 이상의 값이어야 합니다.")
private Double dietaryFiber;

@NotNull(message = "열량 정보는 필수입니다.")
@PositiveOrZero(message = "열량은 0 이상의 값이어야 합니다.")
private Double energy;

@NotNull(message = "지방 정보는 필수입니다.")
@PositiveOrZero(message = "지방은 0 이상의 값이어야 합니다.")
private Double fat;

@NotNull(message = "단백질 정보는 필수입니다.")
@PositiveOrZero(message = "단백질은 0 이상의 값이어야 합니다.")
private Double protein;

@NotNull(message = "포화지방 정보는 필수입니다.")
@PositiveOrZero(message = "포화지방은 0 이상의 값이어야 합니다.")
private Double satFat;

@NotNull(message = "나트륨 정보는 필수입니다.")
@PositiveOrZero(message = "나트륨은 0 이상의 값이어야 합니다.")
private Double sodium;

@NotNull(message = "당류 정보는 필수입니다.")
@PositiveOrZero(message = "당류는 0 이상의 값이어야 합니다.")
private Double sugar;

@NotNull(message = "트랜스지방 정보는 필수입니다.")
@PositiveOrZero(message = "트랜스지방은 0 이상의 값이어야 합니다.")
private Double transFat;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.DecodEat.domain.report.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@Builder
@AllArgsConstructor
public class ReportResponseDto {

@NotNull
@Schema(name = "제품 id", example = "1")
Long productId;

@NotNull
@Schema(name = "신고 유형", example = "영양 정보 수정")
String reportContent;
}
26 changes: 26 additions & 0 deletions src/main/java/com/DecodEat/domain/report/entity/ImageReport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.DecodEat.domain.report.entity;


import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;


@Entity
@Table(name = "image_reports")
@Getter
@DiscriminatorValue("INAPPROPRIATE_IMAGE")
@SuperBuilder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ImageReport extends ReportRecord {

@Column(name = "image_url")
private String imageUrl;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.DecodEat.domain.report.entity;

import com.DecodEat.domain.products.entity.Product;
import jakarta.persistence.*;
import lombok.*;
import lombok.experimental.SuperBuilder;

@Entity
@Table(name = "nutrition_reports")
@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DiscriminatorValue("NUTRITION_UPDATE")
public class NutritionReport extends ReportRecord {

@Column(name = "calcium")
private Double calcium;

@Column(name = "carbohydrate")
private Double carbohydrate;

@Column(name = "cholesterol")
private Double cholesterol;

@Column(name = "dietary_fiber")
private Double dietaryFiber;

@Column(name = "energy")
private Double energy;

@Column(name = "fat")
private Double fat;

@Column(name = "protein")
private Double protein;

@Column(name = "sat_fat")
private Double satFat;

@Column(name = "sodium")
private Double sodium;

@Column(name = "sugar")
private Double sugar;

@Column(name = "trans_fat")
private Double transFat;
}
35 changes: 35 additions & 0 deletions src/main/java/com/DecodEat/domain/report/entity/ReportRecord.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.DecodEat.domain.report.entity;

import com.DecodEat.domain.products.entity.Product;
import com.DecodEat.global.common.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.*;
import lombok.*;
import lombok.experimental.SuperBuilder;

@Entity
@Getter
@SuperBuilder // 자식 클래스에서 부모 클래스 필드까지 빌드(컴파일 시점에) <-> @Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED) // 서비스 코드 등 다른 곳에서 의미 없는 빈 객체를 실수로 생성하는 것 예방
@Table(name = "report_records")
@Inheritance(strategy = InheritanceType.JOINED) // JOINED 사용
@DiscriminatorColumn(name = "REPORT_TYPE") // 자식 엔티티를 구분할 컬럼 (JPA가 생성)
public abstract class ReportRecord extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "product_id", nullable = false)
private Product product;

@Column(nullable = false)
private Long reporterId;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
@Schema(name = "처리 상태", example = "IN_PROGRESS")
private ReportStatus reportStatus;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.DecodEat.domain.report.entity;

public enum ReportStatus {
IN_PROGRESS,
UPDATED,
CHECKED
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.DecodEat.domain.report.repository;

import com.DecodEat.domain.report.entity.ImageReport;
import com.DecodEat.domain.report.entity.NutritionReport;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.awt.*;

@Repository
public interface ImageReportRepository extends JpaRepository<ImageReport, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.DecodEat.domain.report.repository;

import com.DecodEat.domain.report.entity.NutritionReport;
import com.DecodEat.domain.report.entity.ReportRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface NutritionReportRepository extends JpaRepository<NutritionReport, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.DecodEat.domain.report.repository;

import com.DecodEat.domain.report.entity.ReportRecord;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ReportRecordRepository extends JpaRepository<ReportRecord, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.DecodEat.domain.report.service;

import com.DecodEat.domain.products.entity.Product;
import com.DecodEat.domain.products.repository.ProductRepository;
import com.DecodEat.domain.report.converter.ReportConverter;
import com.DecodEat.domain.report.dto.request.ProductNutritionUpdateRequestDto;
import com.DecodEat.domain.report.dto.response.ReportResponseDto;
import com.DecodEat.domain.report.repository.ImageReportRepository;
import com.DecodEat.domain.report.repository.NutritionReportRepository;
import com.DecodEat.domain.users.entity.User;
import com.DecodEat.global.exception.GeneralException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.DecodEat.global.apiPayload.code.status.ErrorStatus.*;

@Service
@RequiredArgsConstructor
@Transactional
public class ReportService {
private final ProductRepository productRepository;
private final NutritionReportRepository nutritionReportRepository;
private final ImageReportRepository imageReportRepository;

public ReportResponseDto requestUpdateNutrition(User user, Long productId, ProductNutritionUpdateRequestDto requestDto){

Product productProxy = productRepository.getReferenceById(productId); //SELECT 쿼리 없이 ID만 가진 프록시 객체를 가져옴

nutritionReportRepository.save(ReportConverter.toNutritionReport(user.getId(), productProxy, requestDto));

return ReportConverter.toReportResponseDto(productId,"상품 정보 업데이트 요청 완료");
}

public ReportResponseDto requestCheckImage(User user, Long productId, String imageUrl){

Product productProxy = productRepository.getReferenceById(productId); //SELECT 쿼리 없이 ID만 가진 프록시 객체를 가져옴

imageReportRepository.save(ReportConverter.toImageReport(user.getId(), productProxy, imageUrl));

return ReportConverter.toReportResponseDto(productId,"상품 사진 확인 요청 완료");
}

}
Loading
Loading