Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3df4d3d
Merge pull request #267 from pirogramming/main
Imggaggu Jun 18, 2025
ed5756e
Merge pull request #268 from pirogramming/main
Imggaggu Jun 18, 2025
d2e5135
[Fix] 상태 수정수정
Imggaggu Jun 18, 2025
e226449
[add]: data 구조 확인용 로그 추가
NamKyeongMin Jun 20, 2025
a9e17f3
Merge pull request #269 from pirogramming/frontend_km
NamKyeongMin Jun 20, 2025
8d3cdc5
[fix]: 날짜 변경 시 리로딩 로직 수정
NamKyeongMin Jun 20, 2025
3d303eb
Merge pull request #270 from pirogramming/frontend_km
NamKyeongMin Jun 20, 2025
5fd41b3
[fix]: 날짜 변경 리로딩 로직 수정(useRef로 변경)
NamKyeongMin Jun 20, 2025
15dd66d
Merge pull request #271 from pirogramming/frontend_km
NamKyeongMin Jun 20, 2025
bac5050
[fix]: 날짜 비교 기준 확인 로직 추가
NamKyeongMin Jun 20, 2025
e19bed3
Merge pull request #272 from pirogramming/frontend_km
NamKyeongMin Jun 20, 2025
a0da5f6
[fix]deposit update
seonjuuu Jun 20, 2025
17160d3
Merge pull request #273 from pirogramming/backend_sj
seonjuuu Jun 20, 2025
8daf040
[fix]: currentDateRef 업데이트 오류 수정
NamKyeongMin Jun 20, 2025
d591d75
Merge pull request #274 from pirogramming/frontend_km
NamKyeongMin Jun 20, 2025
6a43284
[fix] deposit update
seonjuuu Jun 20, 2025
fc3bdd5
Merge pull request #275 from pirogramming/backend_sj
seonjuuu Jun 20, 2025
ae530c1
[fix]: 기존 UTC(KST+9) -> KST(한국 기준 시간)로 시간대 변환
NamKyeongMin Jun 20, 2025
54e5e5c
Merge pull request #276 from pirogramming/frontend_km
NamKyeongMin Jun 20, 2025
51cd458
[fix] deposit update
seonjuuu Jun 20, 2025
a7bd176
Merge pull request #277 from pirogramming/backend_sj
seonjuuu Jun 20, 2025
59c01e5
[fix]: console log 수정 및 weekly count 현황 확인 console 추가
NamKyeongMin Jun 21, 2025
6a1dfe3
Merge pull request #278 from pirogramming/frontend_km
NamKyeongMin Jun 21, 2025
d7f9829
[fix] deposit update
seonjuuu Jun 21, 2025
bd37471
[fix]과제 기본 세팅 변경
seonjuuu Jun 21, 2025
b9ae6f4
Merge pull request #279 from pirogramming/backend_sj
seonjuuu Jun 21, 2025
aec638e
[fix] deposit update
seonjuuu Jun 21, 2025
6889111
Merge pull request #280 from pirogramming/backend_sj
seonjuuu Jun 21, 2025
3ab6ce4
Merge pull request #281 from pirogramming/main
Imggaggu Jun 23, 2025
8c0950b
Update ManageTask.module.css
Imggaggu Jun 23, 2025
7d856bf
Update ManageTask.module.css
Imggaggu Jun 23, 2025
ae17649
update root.css
Imggaggu Jun 29, 2025
8feea8f
merge origin
Imggaggu Jun 29, 2025
c8ec758
[Fix] attendance update
Imggaggu Jun 29, 2025
9d491f4
[Fix] add week map
Imggaggu Jun 29, 2025
0ab9bb3
[Fix] classes=> date
Imggaggu Jun 29, 2025
0f0d150
[Fix] 출석수정 모달
Imggaggu Jun 29, 2025
0c73fa0
[Fix] 출석수정 모달
Imggaggu Jun 29, 2025
d3def1f
[Fix] 출석수정 모달
Imggaggu Jun 29, 2025
0bd265d
[Fix] selecteddate data 구조
Imggaggu Jun 30, 2025
585d779
[Fix] week date 구분자 변경
Imggaggu Jun 30, 2025
aca843e
[Fix] week date 구분자 변경
Imggaggu Jun 30, 2025
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 @@ -13,6 +13,9 @@
import backend.pirocheck.Assignment.entity.AssignmentStatus;
import backend.pirocheck.Assignment.repository.AssignmentItemRepository;
import backend.pirocheck.Assignment.repository.AssignmentRepository;
import backend.pirocheck.Deposit.entity.Deposit;
import backend.pirocheck.Deposit.repository.DepositRepository;
import backend.pirocheck.Deposit.service.DepositService;
import backend.pirocheck.User.entity.Role;
import backend.pirocheck.User.entity.User;
import backend.pirocheck.User.repository.UserRepository;
Expand All @@ -33,6 +36,7 @@ public class AssignmentService {
private final AssignmentItemRepository assignmentItemRepository;
private final AssignmentRepository assignmentRepository;
private final UserRepository userRepository;
private final DepositService depositService;

public List<AssignmentWeekRes> search(Long userId) {

Expand Down Expand Up @@ -95,14 +99,18 @@ public String createAssignment(AssignmentCreateReq assignmentCreateReq) {

for (User user : users) {

AssignmentItem item = AssignmentItem.create(user, assignment, AssignmentStatus.INSUFFICIENT);
AssignmentItem item = AssignmentItem.create(user, assignment, AssignmentStatus.SUCCESS);

assignment.addAssignmentItem(item);
user.addAssignmentItem(item);

// assignmentItemRepository.save(item);
// Cascade 설정이 되어있으므로 assignment = assignmentRepository.save(assignment); 이 코드를 실행할 때 연관된 AssignmentItem도 함께 저장 됨
}
// assignment 저장 후 모든 유저 보증금 재계산
for (User user : users) {
depositService.recalculateDeposit(user.getId());
}

return assignment.getAssignmentName();
}
Expand Down Expand Up @@ -132,6 +140,13 @@ public List<AssignmentRes> searchAssignment(AssignmentRes assignmentRes) {
// 과제 삭제
public String deleteAssignment(Long assignmentId) {
assignmentRepository.deleteById(assignmentId);

// 모든 MEMBER 유저 보증금 재계산
List<User> members = userRepository.findByRole(Role.MEMBER);
for (User user : members) {
depositService.recalculateDeposit(user.getId());
}

return "과제가 성공적으로 삭제되었습니다.";
}

Expand Down Expand Up @@ -163,6 +178,9 @@ public AssignmentStatus createAssignmentItem(Long userId, Long assignmentId, Ass

assignmentItemRepository.save(assignmentItem);

// 보증금 즉시 재계산
depositService.recalculateDeposit(userId);

return assignmentItem.getSubmitted();
}

Expand All @@ -177,10 +195,12 @@ public AssignmentStatus updateAssignmentItem(Long userId, Long assignmentId, Ass
AssignmentItem assignmentItem = assignmentItemRepository.findByUserAndAssignment(user, assignment)
.orElseThrow(() -> new IllegalArgumentException("해당 유저의 과제 채점 결과가 없습니다."));

assignmentItem.update(req.getStatus()); // 상태 업데이트

assignmentItem.update(req.getStatus()); // 상태 업데이트
assignmentItemRepository.save(assignmentItem); // 상태 저장

// 보증금 즉시 재계산
depositService.recalculateDeposit(userId);
return assignmentItem.getSubmitted();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ public interface AttendanceRepository extends JpaRepository<Attendance, Long> {

// 특정 날짜와 차수에 대한 모든 출석 기록 조회
List<Attendance> findByDateAndOrder(LocalDate date, int order);

// 보증금
List<Attendance> findByDateAndOrderAndStatusFalse(LocalDate date, int order);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package backend.pirocheck.Attendance.service;

import backend.pirocheck.Deposit.entity.Deposit;
import backend.pirocheck.Deposit.repository.DepositRepository;
import backend.pirocheck.Deposit.service.DepositService;
import backend.pirocheck.User.entity.Role;
import backend.pirocheck.User.entity.User;
import backend.pirocheck.User.repository.UserRepository;
Expand Down Expand Up @@ -30,6 +33,7 @@ public class AttendanceService {
private final AttendanceRepository attendanceRepository;
private final AttendanceCodeRepository attendanceCodeRepository;
private final UserRepository userRepository;
private final DepositService depositService;

// 출석코드 생성 함수
@Transactional
Expand Down Expand Up @@ -121,6 +125,13 @@ public String expireAttendanceCode(String code) {
attendanceCode.setExpired(true);
attendanceCodeRepository.save(attendanceCode);

// 보증금
List<Attendance> absents = attendanceRepository.findByDateAndOrderAndStatusFalse(
attendanceCode.getDate(), attendanceCode.getOrder());

for (Attendance attendance : absents) {
depositService.recalculateDeposit(attendance.getUser().getId());
}
return "출석 코드가 성공적으로 만료되었습니다";
}

Expand Down Expand Up @@ -171,6 +182,9 @@ public AttendanceMarkResponse markAttendance(Long userId, String inputCode) {
attendance.setStatus(true);
attendanceRepository.save(attendance);

//보증금 재계산
depositService.recalculateDeposit(userId);

return AttendanceMarkResponse.success();
}

Expand Down Expand Up @@ -223,6 +237,10 @@ public boolean updateAttendanceStatus(Long attendanceId, boolean status) {
Attendance attendance = attendanceOpt.get();
attendance.setStatus(status);
attendanceRepository.save(attendance);

// 출석 변경 → 보증금 재계산
depositService.recalculateDeposit(attendance.getUser().getId());

return true;
}

Expand Down Expand Up @@ -279,8 +297,14 @@ public boolean deleteAttendance(Long attendanceId) {
if (attendanceOpt.isEmpty()) {
return false;
}

attendanceRepository.delete(attendanceOpt.get());

Attendance attendance = attendanceOpt.get(); // 변수로 저장
Long userId = attendance.getUser().getId();

attendanceRepository.delete(attendance);

// 출석 삭제 후 보증금 재계산
depositService.recalculateDeposit(userId);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,40 @@ public DepositResDto getDeposit(Long userId) {
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));

Deposit deposit = depositRepository.findByUser(user);
calculateAndSave(user, deposit);

// 출석 실패
return DepositResDto.builder()
.amount(deposit.getAmount())
.descentAssignment(deposit.getDescentAssignment())
.descentAttendance(deposit.getDescentAttendance())
.ascentDefence(deposit.getAscentDefence())
.build();
}

// 보증금 재계산 (내부 로직만 수행)
@Transactional
public void recalculateDeposit(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));

Deposit deposit = depositRepository.findByUser(user);
calculateAndSave(user, deposit);
}

// 공통 계산 로직
private void calculateAndSave(User user, Deposit deposit) {
//출석
int failAttendanceCount = attendanceRepository.countByUserAndStatusFalse(user);
int descentAttendance = failAttendanceCount * 10_000;

// 과제 실패
//과제
int failAssignmentCount = assignmentItemRepository.countByUserAndSubmitted(user, AssignmentStatus.FAILURE);
int weakAssignmentCount = assignmentItemRepository.countByUserAndSubmitted(user, AssignmentStatus.INSUFFICIENT);
int descentAssignment = failAssignmentCount * 20_000 + weakAssignmentCount * 10_000;

// 방어권
int ascentDefence = deposit.getAscentDefence();

// 보증금 업데이트
deposit.updateAmounts(descentAssignment, descentAttendance, ascentDefence);
depositRepository.save(deposit);

return DepositResDto.builder()
.amount(deposit.getAmount())
.descentAssignment(deposit.getDescentAssignment())
.descentAttendance(deposit.getDescentAttendance())
.ascentDefence(deposit.getAscentDefence())
.build();

}
}
24 changes: 12 additions & 12 deletions frontend/src/components/AdminDailyAttendanceCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import "./componentsCss/AdminDailyAttendanceCard.css";
import api from "../api/api";
import { getStudentAttendance,updateAttendanceStatus } from "../api/adminattendance";

const AdminDailyAttendanceCard = ({ date, order,studentId, onClose, onRefresh }) => {
const AdminDailyAttendanceCard = ({ date, studentId, onClose, onRefresh }) => {
const [slots, setSlots] = useState([]);
const [modified, setModified] = useState([]);

Expand Down Expand Up @@ -34,22 +34,22 @@ const AdminDailyAttendanceCard = ({ date, order,studentId, onClose, onRefresh }
*/
const rawSlots = rawData
.filter((d) => d.date === date) // 해당 날짜의 출석만 필터
.sort((a, b) => a.order - b.order) // order 순으로 정렬
//.sort((a, b) => a.order - b.order) // order 순으로 정렬
.map((d) => ({
date: d.date,
//date: d.date,
id: d.attendanceId, // 출석 ID
order: d.order, // 회차 표시용
//order: d.order, // 회차 표시용
status: d.status ? "SUCCESS" : "FAILURE", // 드롭다운에 맞게 변환
}));

const filledSlots =
rawSlots.length > 0
? rawSlots
: [1, 2, 3].map((order) => ({
date,
//date,
id: null, // 새 출석이므로 아직 id 없음
order,
status: "EMPTY",//기본값
//order,
status: "FAILURE",//기본값
}));

setSlots(filledSlots);
Expand All @@ -63,9 +63,9 @@ const AdminDailyAttendanceCard = ({ date, order,studentId, onClose, onRefresh }
}
};

fetchSlots();
if (date) fetchSlots();
}, [date, studentId]);

const handleChange = (idx, newValue) => {
const newSlots = [...slots];
newSlots[idx].status = newValue;
Expand All @@ -91,8 +91,8 @@ const AdminDailyAttendanceCard = ({ date, order,studentId, onClose, onRefresh }

console.log("📝 저장 요청", {
id: slot.id,
order: slot.order,
date: slot.date,
//order: slot.order,
//date: slot.date,
status: slot.status,
});

Expand Down Expand Up @@ -126,7 +126,7 @@ const AdminDailyAttendanceCard = ({ date, order,studentId, onClose, onRefresh }
</div>
<div className="card-body">
{slots.map((slot, idx) => (
<div key={`${slot.date}-${slot.order}`} className="slot-row">
<div key={slot.id || `${date}-${idx}`} className="slot-row">
<span>{idx + 1}차 출석</span>
<select value={slot.status} onChange={(e) => handleChange(idx, e.target.value)}>
<option value="SUCCESS">성공</option>
Expand Down
25 changes: 10 additions & 15 deletions frontend/src/components/AdminWeeklyAttendanceList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,19 @@ const statusImageMap = {
const AdminWeeklyAttendanceList = ({ attendanceData, onSelectDate }) => {
return (
<div className="weekly-container">
{attendanceData.map(({ week, classes }) => (
{attendanceData.map(({ week, days}) => (
<div key={week} className="eachWeekInfo" /*onClick={() => onSelectWeek(week)}*/>
<p className="weekInfo">{week}주차</p>
<div className="coin_img_container">
{classes.map((cls, idx) => (
<img key={idx}
src={statusImageMap[cls.status]}
style={{ cursor: "pointer" }}
/*
onClick={() => {
console.log("🧪 클릭됨!", cls.date);
cls.date && onSelectDate(cls.date);
}}
*/
onClick={() => {
console.log("🧪 클릭됨!", cls.date, cls.order);
if (cls.date) onSelectDate({ date: cls.date, order: cls.order });
}}
{days.map((day, idx) => (
<img
key={idx}
src={statusImageMap[day.status]}
style={{ cursor: "pointer" }}
onClick={() => {
console.log("🧪 클릭됨!", day.date);
if (day.date) onSelectDate(day.date );
}}
/>
))}
</div>
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/components/AttendanceWeekInfo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ const AttendanceWeekInfo = ({ week, classes }) => {
<div className="eachWeekInfo">
<p className="weekInfo">{week}주차</p>
<div className="coin_img_container">
{classes.map((cls, idx) => (
<img key={idx} src={cls.image} alt={`${idx + 1}번째 수업`} />
))}
{classes.map((cls, idx) => {
console.log(`week ${week}, idx ${idx}, image:`, cls.image);
return <img key={idx} src={cls.image} alt={`${idx + 1}번째 수업`} />;
})}
</div>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/admin/AdminStudentAssignment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const AdminStudentAssignment = () => {
});
}, [studentId, week]);

const handleStatusChange = (weekIdx, dayIdx, taskIdx, newStatus) => {
const handleStatusChange = (weekNum, dayIdx, taskIdx, newStatus) => {
const weekIdx = weeks.findIndex(w => Number(w.week) === Number(weekNum));
if (weekIdx === -1) return;

Expand Down Expand Up @@ -137,7 +137,7 @@ const AdminStudentAssignment = () => {
value={task.status}
onChange={(e) =>
handleStatusChange(
weekIdx,
weekItem.week,
dayIdx,
taskIdx,
e.target.value
Expand Down
Loading