Skip to content

Commit a1167f2

Browse files
authored
Merge pull request #64 from DIDIM-ai/fix/#63-delete-update-image
fix: 자녀 삭제 시 불필요한 update 제거 (#63)
2 parents c10f7f0 + b6d3f11 commit a1167f2

File tree

9 files changed

+173
-155
lines changed

9 files changed

+173
-155
lines changed

src/main/java/com/likelion/ai_teacher_a/domain/image/controller/ImageController.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,16 @@ public class ImageController {
3030
@PostMapping("/upload")
3131
public ResponseEntity<ImageResponseDto> uploadToS3(@RequestParam("file") MultipartFile file,
3232
@LoginUserId Long userId) throws IOException {
33-
User user = userRepository.findById(userId)
34-
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다"));
35-
ImageResponseDto dto = imageService.uploadToS3AndSave(file, ImageType.ETC, user);
33+
34+
ImageResponseDto dto = imageService.uploadToS3AndSave(file, ImageType.ETC, userId);
3635
return ResponseEntity.ok(dto);
3736
}
3837

3938
@Operation(summary = "이미지 URL 조회", description = "이미지 ID를 이용해 S3에 저장된 이미지의 URL을 반환합니다.")
4039
@GetMapping("/{imageId}")
4140
public ResponseEntity<Map<String, Object>> getImageUrl(@PathVariable("imageId") Long imageId, @LoginUserId Long userId) {
42-
User user = userRepository.findById(userId)
43-
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다"));
44-
String url = imageService.getImageUrl(imageId, user);
41+
42+
String url = imageService.getImageUrl(imageId, userId);
4543
return ResponseEntity.ok(Map.of("imageId", imageId, "url", url));
4644
}
4745
}

src/main/java/com/likelion/ai_teacher_a/domain/image/service/ImageService.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.likelion.ai_teacher_a.domain.image.entity.ImageType;
77
import com.likelion.ai_teacher_a.domain.image.repository.ImageRepository;
88
import com.likelion.ai_teacher_a.domain.user.entity.User;
9+
import com.likelion.ai_teacher_a.domain.user.repository.UserRepository;
910
import lombok.RequiredArgsConstructor;
1011
import org.springframework.stereotype.Service;
1112
import org.springframework.transaction.annotation.Transactional;
@@ -20,10 +21,12 @@ public class ImageService {
2021
private final ImageRepository imageRepository;
2122

2223
private final S3Uploader s3Uploader;
24+
private final UserRepository userRepository;
2325

2426

2527
@Transactional
26-
public ImageResponseDto uploadToS3AndSave(MultipartFile file, ImageType type, User user) throws IOException {
28+
public ImageResponseDto uploadToS3AndSave(MultipartFile file, ImageType type, Long userId) throws IOException {
29+
User user = userRepository.getReferenceById(userId);
2730

2831
String url = s3Uploader.upload(file);
2932

@@ -51,11 +54,12 @@ public ImageResponseDto uploadToS3AndSave(MultipartFile file, ImageType type, Us
5154

5255

5356
@Transactional
54-
public void deleteImage(Long imageId, User user) {
57+
public void deleteImage(Long imageId, Long userId) {
58+
User user = userRepository.getReferenceById(userId);
5559
Image image = imageRepository.findById(imageId)
5660
.orElseThrow(() -> new RuntimeException("이미지를 찾을 수 없습니다."));
5761

58-
// S3에서 삭제
62+
5963
if (image.getUrl() != null) {
6064
s3Uploader.delete(image.getUrl());
6165
}
@@ -65,15 +69,17 @@ public void deleteImage(Long imageId, User user) {
6569

6670

6771
@Transactional(readOnly = true)
68-
public String getImageUrl(Long imageId, User user) {
72+
public String getImageUrl(Long imageId, Long userId) {
73+
User user = userRepository.getReferenceById(userId);
6974
Image image = imageRepository.findByImageIdAndUser(imageId, user)
7075
.orElseThrow(() -> new RuntimeException("이미지를 찾을 수 없습니다."));
7176
return image.getUrl();
7277
}
7378

7479

7580
@Transactional
76-
public ImageAndResponseDto uploadToS3AndSaveWithEntity(MultipartFile file, ImageType type, User user) throws IOException {
81+
public ImageAndResponseDto uploadToS3AndSaveWithEntity(MultipartFile file, ImageType type, Long userId) throws IOException {
82+
User user = userRepository.getReferenceById(userId);
7783
String url = s3Uploader.upload(file);
7884

7985
Image image = Image.builder()

src/main/java/com/likelion/ai_teacher_a/domain/logsolve/controller/LogSolveController.java

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.likelion.ai_teacher_a.domain.logsolve.dto.TotalLogCountDto;
44
import com.likelion.ai_teacher_a.domain.logsolve.service.LogSolveService;
5-
import com.likelion.ai_teacher_a.domain.user.entity.User;
65
import com.likelion.ai_teacher_a.domain.user.repository.UserRepository;
76
import com.likelion.ai_teacher_a.domain.userJr.entity.UserJr;
87
import com.likelion.ai_teacher_a.domain.userJr.repository.UserJrRepository;
@@ -17,7 +16,6 @@
1716
import org.springframework.http.HttpStatus;
1817
import org.springframework.http.MediaType;
1918
import org.springframework.http.ResponseEntity;
20-
import org.springframework.security.core.userdetails.UsernameNotFoundException;
2119
import org.springframework.web.bind.annotation.*;
2220
import org.springframework.web.multipart.MultipartFile;
2321

@@ -33,37 +31,36 @@ public class LogSolveController {
3331
private final UserRepository userRepository;
3432
private final UserJrRepository userJrRepository;
3533

34+
private void validateUserJrOwner(Long userId, UserJr userJr) {
35+
if (!userJr.getUser().getId().equals(userId)) {
36+
throw new RuntimeException("해당 자녀에 접근할 권한이 없습니다.");
37+
}
38+
}
39+
3640
@Operation(summary = "이미지 문제 업로드 및 AI 해설 시작")
3741
@PostMapping(value = "/solve", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
3842
public ResponseEntity<?> solveImage(
3943
@RequestParam("mathProblemImage") MultipartFile image,
4044
@RequestParam("userJrId") Long userJrId, // 쿼리 파라미터
4145
@LoginUserId Long userId) {
4246

43-
User user = userRepository.findById(userId)
44-
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다"));
45-
46-
UserJr userJr = userJrRepository.findById(userJrId)
47+
UserJr userJr = userJrRepository.findByIdWithUser(userJrId)
4748
.orElseThrow(() -> new RuntimeException("자녀 정보를 찾을 수 없습니다."));
48-
49-
if (!userJr.getUser().getId().equals(user.getId())) {
50-
throw new RuntimeException("해당 자녀에 접근할 권한이 없습니다.");
51-
}
49+
validateUserJrOwner(userId, userJr);
5250

5351
int grade = userJr.getSchoolGrade();
5452

55-
return logSolveService.handleSolveImage(image, user, userJr, grade);
53+
return logSolveService.handleSolveImage(image, userId, userJr, grade);
54+
5655
}
5756

5857

5958
@Operation(summary = "단일 문제해설 상세 조회")
6059
@GetMapping("/{logSolveId}")
6160
public ResponseEntity<?> getLogDetail(@Parameter(description = "해당 문제해설 로그 ID") @PathVariable("logSolveId") Long logSolveId,
6261
@LoginUserId Long userId) {
63-
User user = userRepository.findById(userId)
64-
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다"));
6562
try {
66-
Map<String, Object> result = logSolveService.getLogDetail(logSolveId, user);
63+
Map<String, Object> result = logSolveService.getLogDetail(logSolveId, userId);
6764
return ResponseEntity.ok(result);
6865
} catch (IllegalArgumentException e) {
6966
return ResponseEntity.status(HttpStatus.NOT_FOUND)
@@ -75,10 +72,8 @@ public ResponseEntity<?> getLogDetail(@Parameter(description = "해당 문제해
7572
@DeleteMapping("/{logSolveId}")
7673
public ResponseEntity<?> deleteLog(@Parameter(description = "삭제할 로그 ID") @PathVariable("logSolveId") Long logSolveId,
7774
@LoginUserId Long userId) {
78-
User user = userRepository.findById(userId)
79-
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다"));
8075
try {
81-
logSolveService.deleteLogById(logSolveId, user);
76+
logSolveService.deleteLogById(logSolveId, userId);
8277
return ResponseEntity.ok(Map.of("message", "삭제가 완료되었습니다."));
8378
} catch (IllegalArgumentException e) {
8479
return ResponseEntity.status(HttpStatus.NOT_FOUND)
@@ -93,9 +88,8 @@ public ResponseEntity<?> askAgain(
9388
@Parameter(description = "사용자의 추가 질문") @RequestParam("question") String question,
9489
@LoginUserId Long userId
9590
) {
96-
User user = userRepository.findById(userId)
97-
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다"));
98-
return logSolveService.executeFollowUp(logSolveId, question, user);
91+
92+
return logSolveService.executeFollowUp(logSolveId, question, userId);
9993
}
10094

10195

@@ -118,18 +112,13 @@ public ResponseEntity<?> getSimpleLogs(
118112
@RequestParam(name = "userJrId") Long userJrId,
119113
@LoginUserId Long userId
120114
) {
121-
User user = userRepository.findById(userId)
122-
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다"));
123-
124-
UserJr userJr = userJrRepository.findById(userJrId)
115+
UserJr userJr = userJrRepository.findByIdWithUser(userJrId)
125116
.orElseThrow(() -> new RuntimeException("자녀 정보를 찾을 수 없습니다."));
117+
validateUserJrOwner(userId, userJr);
126118

127119

128-
if (!userJr.getUser().getId().equals(user.getId())) {
129-
throw new RuntimeException("해당 자녀에 접근할 권한이 없습니다.");
130-
}
120+
Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
131121

132-
Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "image.uploadedAt"));
133122

134123
return ResponseEntity.ok(logSolveService.getAllSimpleLogs(pageable, userJr));
135124
}

src/main/java/com/likelion/ai_teacher_a/domain/logsolve/entity/LogSolve.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@
77
import lombok.*;
88
import org.hibernate.annotations.OnDelete;
99
import org.hibernate.annotations.OnDeleteAction;
10+
import org.springframework.data.annotation.CreatedDate;
11+
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
12+
13+
import java.time.LocalDateTime;
1014

1115
@Entity
1216
@Table(name = "log_solve")
17+
@EntityListeners(AuditingEntityListener.class)
1318
@Getter
1419
@NoArgsConstructor
1520
@AllArgsConstructor
@@ -24,6 +29,9 @@ public class LogSolve {
2429
@JoinColumn(name = "image_id")
2530
private Image image;
2631

32+
@Column(length = 500)
33+
private String problemTitle;
34+
2735

2836
@Column(columnDefinition = "TEXT")
2937
private String result;
@@ -37,5 +45,9 @@ public class LogSolve {
3745
@OnDelete(action = OnDeleteAction.CASCADE)
3846
private UserJr userJr;
3947

48+
@CreatedDate
49+
@Column(updatable = false)
50+
private LocalDateTime createdAt;
51+
4052

4153
}

src/main/java/com/likelion/ai_teacher_a/domain/logsolve/repository/LogSolveRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.likelion.ai_teacher_a.domain.userJr.entity.UserJr;
66
import org.springframework.data.domain.Page;
77
import org.springframework.data.domain.Pageable;
8+
import org.springframework.data.jpa.repository.EntityGraph;
89
import org.springframework.data.jpa.repository.JpaRepository;
910
import org.springframework.data.jpa.repository.Query;
1011
import org.springframework.data.repository.query.Param;
@@ -45,5 +46,9 @@ public interface LogSolveRepository extends JpaRepository<LogSolve, Long> {
4546
Optional<LogSolve> findByIdWithImageAndUser(@Param("logSolveId") Long logSolveId);
4647

4748

49+
@EntityGraph(attributePaths = {"image"})
50+
Page<LogSolve> findAllByUserJr(UserJr userJr, Pageable pageable);
51+
52+
4853
}
4954

0 commit comments

Comments
 (0)