From 9090debb99d6796eb38a9d15139d470f88557cb8 Mon Sep 17 00:00:00 2001 From: lilyyang0077 Date: Sat, 23 May 2026 18:27:08 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=EC=B6=9C=EC=84=9D=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EB=A7=8C=EB=A3=8C=20=EB=90=A0=20=EB=95=8C=EC=97=90?= =?UTF-8?q?=EB=8F=84=20=EB=B3=B4=EC=A6=9D=EA=B8=88=20=EC=B0=A8=EA=B0=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/service/AttendanceService.java | 92 +++++++++++-------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/attendance/service/AttendanceService.java b/backend/src/main/java/com/example/Piroin/project/domain/attendance/service/AttendanceService.java index 1f07b2b..989e3d1 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/attendance/service/AttendanceService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/attendance/service/AttendanceService.java @@ -66,6 +66,18 @@ public AttendanceCode generateCodeAndCreateAttendances(LocalDate date) { // [수 activeCode.expire(); } + for (AttendanceCode activeCode : activeCodes) { + activeCode.expire(); + + List attendances = + attendanceRepository.findByAttendanceCodeId(activeCode.getId()); + + for (Attendance attendance : attendances) { + depositService.recalculateDeposit(attendance.getUser().getId()); + } + } + + // 4. 4자리 랜덤 코드 생성 및 차수(Order) 계산 String code = String.valueOf(ThreadLocalRandom.current().nextInt(1000, 10000)); String attendanceOrder = String.valueOf(codeCountOfDay + 1); // 1회차, 2회차, 3회차 @@ -226,46 +238,46 @@ public List findByUserId(Integer userId) { .sorted(Comparator.comparing(AttendanceStatusRes::getDate).reversed()) .toList(); } - - // 6. 유저 상태 변경 (관리자) - // 컨트롤러 부분은 출석만 받는데 여기는 출석&과제 둘 다 받아서 추후에 수정 예정 - @Transactional - public boolean updateUserStatus(Integer userId, UpdateUserStatusReq req) { - boolean updated = false; - - // 출석 상태 변경 코드 - if (req.getAttendanceId() != null && req.getAttendanceStatus() != null) { - Attendance attendance = attendanceRepository.findById(req.getAttendanceId()) - .orElseThrow(() -> new IllegalArgumentException("출석 기록을 찾을 수 없습니다.")); - - if (!attendance.getUser().getId().equals(userId)) { - throw new IllegalArgumentException("요청된 사용자와 출석 기록의 사용자가 일치하지 않습니다."); - } - - attendance.updateStatus(req.getAttendanceStatus()); - updated = true; - } - - // 과제 상태 변경 코드 - if (req.getAssignmentItemId() != null && req.getAssignmentStatus() != null) { - AssignmentItem assignmentItem = assignmentItemRepository.findById(Math.toIntExact(req.getAssignmentItemId())) - .orElseThrow(() -> new IllegalArgumentException("과제 기록을 찾을 수 없습니다.")); - - if (!assignmentItem.getUser().getId().equals(userId)) { - throw new IllegalArgumentException("요청된 사용자와 과제 기록의 사용자가 일치하지 않습니다."); - } - - assignmentItem.updateSubmitted(req.getAssignmentStatus()); - updated = true; - } - - // 출석 변경 → 보증금 재계산 (과제 변경도 포함이 되어 있나..?) - if (updated) { - depositService.recalculateDeposit(Long.valueOf(userId)); - } - - return updated; - } +// +// // 6. 유저 상태 변경 (관리자) +// // 컨트롤러 부분은 출석만 받는데 여기는 출석&과제 둘 다 받아서 추후에 수정 예정 +// @Transactional +// public boolean updateUserStatus(Integer userId, UpdateUserStatusReq req) { +// boolean updated = false; +// +// // 출석 상태 변경 코드 +// if (req.getAttendanceId() != null && req.getAttendanceStatus() != null) { +// Attendance attendance = attendanceRepository.findById(req.getAttendanceId()) +// .orElseThrow(() -> new IllegalArgumentException("출석 기록을 찾을 수 없습니다.")); +// +// if (!attendance.getUser().getId().equals(userId)) { +// throw new IllegalArgumentException("요청된 사용자와 출석 기록의 사용자가 일치하지 않습니다."); +// } +// +// attendance.updateStatus(req.getAttendanceStatus()); +// updated = true; +// } +// +// // 과제 상태 변경 코드 +// if (req.getAssignmentItemId() != null && req.getAssignmentStatus() != null) { +// AssignmentItem assignmentItem = assignmentItemRepository.findById(Math.toIntExact(req.getAssignmentItemId())) +// .orElseThrow(() -> new IllegalArgumentException("과제 기록을 찾을 수 없습니다.")); +// +// if (!assignmentItem.getUser().getId().equals(userId)) { +// throw new IllegalArgumentException("요청된 사용자와 과제 기록의 사용자가 일치하지 않습니다."); +// } +// +// assignmentItem.updateSubmitted(req.getAssignmentStatus()); +// updated = true; +// } +// +// // 출석 변경 → 보증금 재계산 (과제 변경도 포함이 되어 있나..?) +// if (updated) { +// depositService.recalculateDeposit(Long.valueOf(userId)); +// } +// +// return updated; +// } } From bdfea4668dd203218330be0eb25d5d044bba55e9 Mon Sep 17 00:00:00 2001 From: lilyyang0077 Date: Sat, 23 May 2026 18:27:28 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EB=B6=80=EC=9B=90=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20=EB=B3=B4=EC=A6=9D?= =?UTF-8?q?=EA=B8=88=20=EC=9E=AC=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/AssignmentItemRepository.java | 2 + .../controller/AdminAttendanceController.java | 31 ++-- .../repository/AttendanceRepository.java | 6 +- .../domain/deposit/entity/Deposit.java | 17 ++ .../deposit/service/DepositService.java | 2 +- .../domain/user/service/AdminUserService.java | 153 ++++++------------ 6 files changed, 84 insertions(+), 127 deletions(-) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/assignment/repository/AssignmentItemRepository.java b/backend/src/main/java/com/example/Piroin/project/domain/assignment/repository/AssignmentItemRepository.java index ceb82c8..9b2be1e 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/assignment/repository/AssignmentItemRepository.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/assignment/repository/AssignmentItemRepository.java @@ -18,4 +18,6 @@ List findByUserIdAndAssignmentWeek( ); Optional findById(Integer id); + + List findByUserId(Long userId); } diff --git a/backend/src/main/java/com/example/Piroin/project/domain/attendance/controller/AdminAttendanceController.java b/backend/src/main/java/com/example/Piroin/project/domain/attendance/controller/AdminAttendanceController.java index 72d9204..bb1f97c 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/attendance/controller/AdminAttendanceController.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/attendance/controller/AdminAttendanceController.java @@ -67,21 +67,20 @@ public String expireActiveAttendance() { return attendanceService.expireActiveAttendanceCode(); } - // 4. 출석 상태 변경 (관리자 전용) - // 현재는 출석만 변경되지만 나중에 출석 & 과제 변경으로 바꿀 예정 - @Operation(summary = "출석 상태 변경", description = "관리자가 특정 사용자의 출석 상태를 변경합니다.") - @ApiResponses(value = { - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "출석 상태 변경 성공"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 요청"), - @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "출석 기록을 찾을 수 없음") - }) - - @PutMapping("/admin/users/{userId}/status") - public boolean updateUserStatus( - @Parameter(description = "사용자 ID", example = "1") - @PathVariable Integer userId, - @RequestBody UpdateUserStatusReq req) { - return attendanceService.updateUserStatus(userId, req); - } +// // 4. 출석 상태 변경 (관리자 전용) +// // 현재는 출석만 변경되지만 나중에 출석 & 과제 변경으로 바꿀 예정 +// @Operation(summary = "출석 상태 변경", description = "관리자가 특정 사용자의 출석 상태를 변경합니다.") +// @ApiResponses(value = { +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "출석 상태 변경 성공"), +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "잘못된 요청"), +// @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "출석 기록을 찾을 수 없음") +// }) +// @PutMapping("/admin/users/{userId}/status") +// public boolean updateUserStatus( +// @Parameter(description = "사용자 ID", example = "1") +// @PathVariable Integer userId, +// @RequestBody UpdateUserStatusReq req) { +// return attendanceService.updateUserStatus(userId, req); +// } } diff --git a/backend/src/main/java/com/example/Piroin/project/domain/attendance/repository/AttendanceRepository.java b/backend/src/main/java/com/example/Piroin/project/domain/attendance/repository/AttendanceRepository.java index c386e4b..2f3b99f 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/attendance/repository/AttendanceRepository.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/attendance/repository/AttendanceRepository.java @@ -16,10 +16,6 @@ public interface AttendanceRepository extends JpaRepository { Optional findById(Integer id); - // List findByUserId(Long userId); - - //Optional findByUserIdAndStudySessionId(Integer userId, Long studySessionId); - // 연관관계 필드명이 attendanceCode 라면 내부 ID인 Id를 조합하여 명명 Optional findByUserIdAndAttendanceCodeId(Long userId, Long attendanceCodeId); @@ -43,6 +39,8 @@ Optional findByUserIdAndAttendanceCodeId( Integer attendanceCodeId ); + List findByAttendanceCodeId(Integer id); + // 특정 날짜에 발급된 출석 코드의 개수를 세는 메서드 //long countByAttendanceDate(String attendanceDate); diff --git a/backend/src/main/java/com/example/Piroin/project/domain/deposit/entity/Deposit.java b/backend/src/main/java/com/example/Piroin/project/domain/deposit/entity/Deposit.java index 2fee4c3..38a958d 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/deposit/entity/Deposit.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/deposit/entity/Deposit.java @@ -40,6 +40,7 @@ public class Deposit { @Column(name = "ascent_defence", nullable = false) private Integer ascentDefence; + // 출석 차감액만 새로 계산할 때 사용 public void updateAttendanceAmount(Integer descentAttendance) { this.descentAttendance = descentAttendance; @@ -51,6 +52,22 @@ public void updateAttendanceAmount(Integer descentAttendance) { + this.ascentDefence; } + // 과제 차감 + 출석 차감을 한 번에 재계산할 때 사용 + public void updateDepositAmount( + Integer descentAssignment, + Integer descentAttendance + ) { + this.descentAssignment = descentAssignment; + this.descentAttendance = descentAttendance; + + int baseAmount = 100_000; + + this.amount = baseAmount + - this.descentAssignment + - this.descentAttendance + + this.ascentDefence; + } + } diff --git a/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java b/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java index 404b437..9b4ecdc 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java @@ -22,7 +22,7 @@ public class DepositService { private final UserRepository userRepository; private final AttendanceRepository attendanceRepository; - // 보증금 재계산 로직 (운영진이 출석/과제 여부 수정 시) + // 보증금 재계산 로직 (운영진이 출석/과제 여부 수정 시, 출석코드 만료 시) @Transactional public void recalculateDeposit(Long userId) { User user = userRepository.findById(userId) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java index 6cfa315..b098403 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java @@ -2,12 +2,15 @@ import com.example.Piroin.project.domain.assignment.entity.Assignment; import com.example.Piroin.project.domain.assignment.entity.AssignmentItem; +import com.example.Piroin.project.domain.assignment.enums.AssignmentStatus; import com.example.Piroin.project.domain.assignment.repository.AssignmentItemRepository; import com.example.Piroin.project.domain.assignment.repository.AssignmentRepository; import com.example.Piroin.project.domain.attendance.entity.Attendance; import com.example.Piroin.project.domain.attendance.repository.AttendanceCodeRepository; import com.example.Piroin.project.domain.attendance.repository.AttendanceRepository; import com.example.Piroin.project.domain.curriculum.repository.CurriculumRepository; +import com.example.Piroin.project.domain.deposit.entity.Deposit; +import com.example.Piroin.project.domain.deposit.repository.DepositRepository; import com.example.Piroin.project.domain.user.dto.*; import com.example.Piroin.project.domain.user.entity.User; import com.example.Piroin.project.domain.user.enums.Role; @@ -29,6 +32,7 @@ public class AdminUserService { private final UserService userService; private final AssignmentItemRepository assignmentItemRepository; private final AttendanceRepository attendanceRepository; + private final DepositRepository depositRepository; private final CurriculumRepository curriculumRepository; private final AssignmentRepository assignmentRepository; private final AttendanceCodeRepository attendanceCodeRepository; @@ -69,13 +73,9 @@ public UpdateStudentStatusResponse updateStudentWeekStatus( ) { User user = userRepository.findById(userId) - .orElseThrow(() -> - new RuntimeException("사용자가 존재하지 않습니다.") - ); + .orElseThrow(() -> new RuntimeException("사용자가 존재하지 않습니다.")); - // 과제 상태 수정 if (request.getAssignments() != null) { - for (UpdateStudentStatusRequest.AssignmentStatusRequest dto : request.getAssignments()) { @@ -85,21 +85,17 @@ public UpdateStudentStatusResponse updateStudentWeekStatus( new RuntimeException("과제 정보가 존재하지 않습니다.") ); - // 본인 데이터 검증 if (!assignmentItem.getUser().getId().equals(userId)) { throw new RuntimeException("해당 유저의 과제가 아닙니다."); } - // PATCH 방식 -> null이면 수정 안 함 if (dto.getSubmitted() != null) { assignmentItem.updateSubmitted(dto.getSubmitted()); } } } - // 출석 상태 수정 if (request.getAttendances() != null) { - for (UpdateStudentStatusRequest.AttendanceStatusRequest dto : request.getAttendances()) { @@ -109,18 +105,18 @@ public UpdateStudentStatusResponse updateStudentWeekStatus( new RuntimeException("출석 정보가 존재하지 않습니다.") ); - // 본인 데이터 검증 if (!attendance.getUser().getId().equals(userId)) { throw new RuntimeException("해당 유저의 출석이 아닙니다."); } - // PATCH 방식 if (dto.getStatus() != null) { attendance.updateStatus(dto.getStatus()); } } } + recalculateDeposit(userId); + return new UpdateStudentStatusResponse( userId, week, @@ -128,99 +124,44 @@ public UpdateStudentStatusResponse updateStudentWeekStatus( ); } -// // 5. 부원 출석/과제 상태 조회 -// @Transactional(readOnly = true) -// public StudentWeeklyStatusResponse getStudentWeeklyStatus( -// Long userId, -// Long week -// ) { -// -// List sessions = -// curriculumRepository.findByWeek(week); -// -// List dayResponses = new ArrayList<>(); -// -// for (StudySession session : sessions) { -// -// LocalDate sessionDate = session.getSessionDate(); -// -// String day = -// sessionDate.getDayOfWeek().toString(); -// -// /* -// * 과제 조회 -// */ -// List assignments = -// assignmentRepository.findBySessionDate(sessionDate); -// -// List assignmentResponses = -// assignments.stream() -// .map(assignment -> { -// -// AssignmentItem item = -// assignmentItemRepository -// .findByUserIdAndAssignmentId( -// userId, -// assignment.getId() -// ) -// .orElse(null); -// -// String submitted = -// item == null -// ? "PENDING" -// : item.getSubmitted().name(); -// -// return AssignmentStatusResponse.builder() -// .assignmentId(assignment.getId()) -// .title(assignment.getTitle()) -// .submitted(submitted) -// .build(); -// }) -// .toList(); -// -// /* -// * 출석 조회 -// */ -// List attendanceCodes = -// attendanceCodeRepository.findByAttendanceDate(sessionDate); -// -// List attendanceResponses = -// attendanceCodes.stream() -// .map(code -> { -// -// Attendance attendance = -// attendanceRepository -// .findByUserIdAndAttendanceCodeId( -// userId, -// code.getId() -// ) -// .orElse(null); -// -// boolean attended = -// attendance != null && -// attendance.getStatus(); -// -// return AttendanceStatusResponse.builder() -// .attendanceCodeId(code.getId()) -// .attendanceOrder(code.getAttendanceOrder()) -// .attended(attended) -// .build(); -// }) -// .toList(); -// -// dayResponses.add( -// DayStatusResponse.builder() -// .day(day) -// .sessionDate(sessionDate) -// .assignments(assignmentResponses) -// .attendances(attendanceResponses) -// .build() -// ); -// } -// -// return StudentWeeklyStatusResponse.builder() -// .week(week) -// .days(dayResponses) -// .build(); -// } + + // 4. 보증금 재계산 메소드(출석 & 과제) + private void recalculateDeposit(Long userId) { + + Deposit deposit = depositRepository.findByUserId(userId) + .orElseThrow(() -> new RuntimeException("보증금 정보가 존재하지 않습니다.")); + + List assignmentItems = + assignmentItemRepository.findByUserId(userId); + + int assignmentPenalty = assignmentItems.stream() + .mapToInt(item -> calculateAssignmentPenalty(item.getSubmitted())) + .sum(); + + List attendances = + attendanceRepository.findByUserId(userId); + + int attendancePenalty = attendances.stream() + .mapToInt(attendance -> attendance.getStatus() ? 0 : 10_000) + .sum(); + + deposit.updateDepositAmount( + assignmentPenalty, + attendancePenalty + ); + } + + // 5. 과제에 대한 보증금 계산 로직 + private int calculateAssignmentPenalty(AssignmentStatus status) { + + return switch (status) { + case SUCCESS, PENDING -> 0; + case INSUFFICIENT -> 10_000; + case FAILURE -> 20_000; + }; + } + + // 6. 출석에 대한 보증금 계산 로직 + // (AttendanceService에 있음!!) + } \ No newline at end of file From 2608b9e0dcf22e87856f8282b3df94d5ffe0ac4b Mon Sep 17 00:00:00 2001 From: lilyyang0077 Date: Sat, 23 May 2026 18:41:51 +0900 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=EA=B3=BC=EC=A0=9C=20=EB=AF=B8?= =?UTF-8?q?=EC=A0=9C=EC=B6=9C=20=EB=B3=B4=EC=A6=9D=EA=B8=88=20=EC=B0=A8?= =?UTF-8?q?=EA=B0=90=203=EB=A7=8C=EC=9B=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Piroin/project/domain/deposit/service/DepositService.java | 4 ++-- .../Piroin/project/domain/user/service/AdminUserService.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java b/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java index 9b4ecdc..b620b11 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/deposit/service/DepositService.java @@ -22,7 +22,7 @@ public class DepositService { private final UserRepository userRepository; private final AttendanceRepository attendanceRepository; - // 보증금 재계산 로직 (운영진이 출석/과제 여부 수정 시, 출석코드 만료 시) + // 1. 보증금 재계산 로직 (운영진이 출석/과제 여부 수정 시, 출석코드 만료 시) @Transactional public void recalculateDeposit(Long userId) { User user = userRepository.findById(userId) @@ -37,7 +37,7 @@ public void recalculateDeposit(Long userId) { deposit.updateAttendanceAmount(descentAttendance); } - // 보증금 조회 로직 + // 2. 보증금 조회 로직 public DepositResponse getMyDeposit(Long userId) { Deposit deposit = depositRepository.findByUserId(userId) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java index b098403..7965058 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java @@ -157,7 +157,7 @@ private int calculateAssignmentPenalty(AssignmentStatus status) { return switch (status) { case SUCCESS, PENDING -> 0; case INSUFFICIENT -> 10_000; - case FAILURE -> 20_000; + case FAILURE -> 30_000; }; } From 326bd604d1c71fd8fcfac66bff1511330741600d Mon Sep 17 00:00:00 2001 From: lilyyang0077 Date: Sat, 23 May 2026 18:56:02 +0900 Subject: [PATCH 4/6] =?UTF-8?q?fix:=20=EA=B3=BC=EC=A0=9C=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=202=EA=B0=9C=EB=A1=9C=20=EB=82=98=EB=88=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/assignment/enums/AssignmentStatus.java | 14 ++++++++++---- .../domain/user/service/AdminUserService.java | 7 ++++++- .../db/migration/V4__add_assignment_status.sql | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 backend/src/main/resources/db/migration/V4__add_assignment_status.sql diff --git a/backend/src/main/java/com/example/Piroin/project/domain/assignment/enums/AssignmentStatus.java b/backend/src/main/java/com/example/Piroin/project/domain/assignment/enums/AssignmentStatus.java index 49315aa..e3902db 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/assignment/enums/AssignmentStatus.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/assignment/enums/AssignmentStatus.java @@ -1,8 +1,14 @@ package com.example.Piroin.project.domain.assignment.enums; public enum AssignmentStatus { - SUCCESS, - INSUFFICIENT, - FAILURE, - PENDING + + SUCCESS, // 정상 제출 (0원) + + INSUFFICIENT_MINOR, // 경미한 불충분 (-10000) + + INSUFFICIENT_MAJOR, // 심각한 불충분 (-20000) + + FAILURE, // 미제출 (-20000) + + PENDING // 아직 채점 안 됨 } diff --git a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java index 7965058..033e89a 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java @@ -155,8 +155,13 @@ private void recalculateDeposit(Long userId) { private int calculateAssignmentPenalty(AssignmentStatus status) { return switch (status) { + case SUCCESS, PENDING -> 0; - case INSUFFICIENT -> 10_000; + + case INSUFFICIENT_MINOR -> 10_000; + + case INSUFFICIENT_MAJOR -> 20_000; + case FAILURE -> 30_000; }; } diff --git a/backend/src/main/resources/db/migration/V4__add_assignment_status.sql b/backend/src/main/resources/db/migration/V4__add_assignment_status.sql new file mode 100644 index 0000000..dc1b61a --- /dev/null +++ b/backend/src/main/resources/db/migration/V4__add_assignment_status.sql @@ -0,0 +1,14 @@ +ALTER TABLE assignment_item + DROP CONSTRAINT chk_assignment_item_submitted; + +ALTER TABLE assignment_item + ADD CONSTRAINT chk_assignment_item_submitted + CHECK ( + submitted IN ( + 'SUCCESS', + 'INSUFFICIENT_MINOR', + 'INSUFFICIENT_MAJOR', + 'FAILURE', + 'PENDING' + ) + ); \ No newline at end of file From 54c3350416992434cd5eb248d26b5b8c79fa044b Mon Sep 17 00:00:00 2001 From: lilyyang0077 Date: Sun, 24 May 2026 11:37:33 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../curriculum/exception/code/CurriculumErrorCode.java | 2 +- .../Piroin/project/domain/user/service/AdminUserService.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/curriculum/exception/code/CurriculumErrorCode.java b/backend/src/main/java/com/example/Piroin/project/domain/curriculum/exception/code/CurriculumErrorCode.java index b7b07ec..07258ef 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/curriculum/exception/code/CurriculumErrorCode.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/curriculum/exception/code/CurriculumErrorCode.java @@ -29,7 +29,7 @@ public enum CurriculumErrorCode { SESSION_DATE_NOT_FOUND( HttpStatus.BAD_REQUEST, "CURRICULUM405", - "해당 날짜의 세션이 없습니다. 세션을 먼저 생성해주세요." + "해당 주차/요일의 세션이 존재하지 않습니다. 세션을 먼저 생성해주세요." ); private final HttpStatus status; diff --git a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java index 033e89a..4e923a8 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/user/service/AdminUserService.java @@ -79,12 +79,14 @@ public UpdateStudentStatusResponse updateStudentWeekStatus( for (UpdateStudentStatusRequest.AssignmentStatusRequest dto : request.getAssignments()) { + // 해당 assignmentItem 존재하지 않을 때 AssignmentItem assignmentItem = assignmentItemRepository.findById(dto.getAssignmentItemId()) .orElseThrow(() -> new RuntimeException("과제 정보가 존재하지 않습니다.") ); + // assignmentItem가 userId의 과제가 아닐 경우 if (!assignmentItem.getUser().getId().equals(userId)) { throw new RuntimeException("해당 유저의 과제가 아닙니다."); } @@ -105,6 +107,7 @@ public UpdateStudentStatusResponse updateStudentWeekStatus( new RuntimeException("출석 정보가 존재하지 않습니다.") ); + // assignmentId가 userId의 것이 아닐 때 if (!attendance.getUser().getId().equals(userId)) { throw new RuntimeException("해당 유저의 출석이 아닙니다."); } @@ -125,7 +128,7 @@ public UpdateStudentStatusResponse updateStudentWeekStatus( } - // 4. 보증금 재계산 메소드(출석 & 과제) + // 4. 보증금 재계산 메소드(출석 & 과제 공통) private void recalculateDeposit(Long userId) { Deposit deposit = depositRepository.findByUserId(userId) From 1d0717241b3cdd7cc66db85f3ecf527b2b1e0352 Mon Sep 17 00:00:00 2001 From: lilyyang0077 Date: Sun, 24 May 2026 12:02:41 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20AssignmentRequest=EC=97=90=EC=84=9C?= =?UTF-8?q?=20id=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project/domain/assignment/dto/CreateAssignmentRequest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/main/java/com/example/Piroin/project/domain/assignment/dto/CreateAssignmentRequest.java b/backend/src/main/java/com/example/Piroin/project/domain/assignment/dto/CreateAssignmentRequest.java index 70e6ebd..adec845 100644 --- a/backend/src/main/java/com/example/Piroin/project/domain/assignment/dto/CreateAssignmentRequest.java +++ b/backend/src/main/java/com/example/Piroin/project/domain/assignment/dto/CreateAssignmentRequest.java @@ -7,7 +7,6 @@ @Getter public class CreateAssignmentRequest { - private Integer assignmentId; private String title;