2025. 1. 26. 19:52ㆍ프로젝트
이 코드는 관리자(전문가) 가 유저가 작성한 자가진단에 대해 피드백을 남겨줄수 있게 해주는 api입니다.
코드는 다음과 같습니다.
import pool from "../db/connection.js";
/**
* 🔹 전문가가 배정된 시스템 목록 조회
*/
const getAssignedSystems = async (req, res) => {
const { expertId } = req.query;
console.log("✅ [getAssignedSystems] Received expertId:", expertId);
if (!expertId) {
return res.status(400).json({
resultCode: "F-1",
msg: "전문가 ID가 필요합니다.",
});
}
try {
const query = `
SELECT s.id AS system_id, s.name AS system_name, u.institution_name,
ar.score, ar.grade, ar.feedback_status
FROM assignment a
JOIN systems s ON a.systems_id = s.id
JOIN User u ON s.user_id = u.id
LEFT JOIN assessment_result ar ON s.id = ar.system_id
WHERE a.expert_id = ?;
`;
console.log("🟡 [getAssignedSystems] Running query:", query);
const [results] = await pool.query(query, [expertId]);
console.log("✅ [getAssignedSystems] Query results:", results);
res.status(200).json({
resultCode: "S-1",
msg: "매칭된 시스템 조회 성공",
data: results,
});
} catch (error) {
console.error(
"❌ [getAssignedSystems] 배정된 시스템 조회 실패:",
error.message
);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
}
};
/**
* 🔹 특정 시스템의 자가진단 결과 조회
*/
const getSystemAssessmentResult = async (req, res) => {
const { systemId } = req.query;
console.log("✅ [getSystemAssessmentResult] Received systemId:", systemId);
if (!systemId) {
return res.status(400).json({
resultCode: "F-1",
msg: "시스템 ID가 필요합니다.",
});
}
try {
const query = `
SELECT ar.id AS assessment_id, ar.system_id, ar.user_id, ar.score,
ar.grade, ar.feedback_status, ar.completed_at, u.institution_name
FROM assessment_result ar
JOIN systems s ON ar.system_id = s.id
JOIN User u ON s.user_id = u.id
WHERE ar.system_id = ?;
`;
console.log("🟡 [getSystemAssessmentResult] Running query:", query);
const [results] = await pool.query(query, [systemId]);
console.log("✅ [getSystemAssessmentResult] Query results:", results);
if (results.length === 0) {
console.warn(
"⚠️ [getSystemAssessmentResult] No results found for systemId:",
systemId
);
return res.status(404).json({
resultCode: "F-1",
msg: "자가진단 결과를 찾을 수 없습니다.",
});
}
res.status(200).json({
resultCode: "S-1",
msg: "자가진단 결과 조회 성공",
data: results[0],
});
} catch (error) {
console.error(
"❌ [getSystemAssessmentResult] 자가진단 결과 조회 실패:",
error.message
);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
}
};
const SystemsResult = async (req, res) => {
const { userId } = req.query;
if (!userId) {
return res.status(400).json({
resultCode: "F-1",
msg: "기관회원 ID가 필요합니다.",
});
}
try {
const query = `
SELECT s.id AS system_id, s.name AS system_name,
ar.score, ar.grade, ar.feedback_status, ar.completed_at,
f.feedback_content, e.name AS expert_name
FROM systems s
LEFT JOIN assessment_result ar ON s.id = ar.system_id
LEFT JOIN assignment a ON s.id = a.systems_id
LEFT JOIN feedback f ON ar.id = f.assessment_result_id
LEFT JOIN expert e ON a.expert_id = e.id
WHERE s.user_id = ?;
`;
const [results] = await pool.query(query, [userId]);
res.status(200).json({
resultCode: "S-1",
msg: "시스템 결과 조회 성공",
data: results,
});
} catch (error) {
console.error("기관회원 시스템 결과 조회 실패:", error.message);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
}
};
const updateQuantitativeFeedback = async (req, res) => {
const { systemId, feedbackResponses } = req.body;
if (!systemId || !Array.isArray(feedbackResponses)) {
console.error("Invalid data format:", { systemId, feedbackResponses });
return res.status(400).json({
resultCode: "F-1",
msg: "잘못된 요청 형식입니다. 'systemId' 및 'feedbackResponses'가 필요합니다.",
});
}
console.log("Received systemId:", systemId);
console.log("Received feedbackResponses:", feedbackResponses);
try {
const query = `
INSERT INTO quantitative (
question_number, system_id, feedback
)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE feedback = VALUES(feedback);
`;
const connection = await pool.getConnection();
await connection.beginTransaction();
for (const { questionNumber, feedback } of feedbackResponses) {
await connection.query(query, [
questionNumber,
systemId,
feedback || "피드백 없음", // 기본값 설정
]);
}
await connection.commit();
connection.release();
res.status(200).json({
resultCode: "S-1",
msg: "정량 피드백 업데이트 성공",
});
} catch (error) {
console.error("Error updating feedback:", error.message);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
}
};
/**
* 🔹 정성 피드백 업데이트
*/
const updateQualitativeFeedback = async (req, res) => {
const { systemId, feedbackResponses } = req.body;
if (!systemId || !feedbackResponses || !Array.isArray(feedbackResponses)) {
console.error("Invalid request data:", { systemId, feedbackResponses });
return res.status(400).json({
resultCode: "F-1",
msg: "잘못된 요청 형식입니다. 'systemId' 및 'feedbackResponses'가 필요합니다.",
});
}
const connection = await pool.getConnection();
try {
const query = `
UPDATE qualitative
SET feedback = ?, additional_comment = ?, response = ?
WHERE question_number = ? AND system_id = ?
`;
await connection.beginTransaction();
for (const response of feedbackResponses) {
const {
questionNumber,
feedback,
additionalComment,
response: userResponse,
} = response;
if (
typeof questionNumber !== "number" ||
typeof feedback !== "string" ||
typeof additionalComment !== "string" ||
typeof userResponse !== "string"
) {
console.error("Invalid feedback response:", response);
throw new Error("피드백 데이터 형식이 잘못되었습니다.");
}
await connection.query(query, [
feedback,
additionalComment,
userResponse,
questionNumber,
systemId,
]);
}
console.log("Feedbacks updated successfully for system_id:", systemId);
// ✅ 전문가 자문 상태 업데이트
const updateStatusQuery = `
UPDATE assessment_result
SET feedback_status = '전문가 자문이 반영되었습니다'
WHERE system_id = ?
`;
const [updateResult] = await connection.query(updateStatusQuery, [
systemId,
]);
console.log(
"Feedback status updated:",
updateResult.affectedRows,
"rows affected"
);
await connection.commit();
console.log("Transaction committed successfully");
res.status(200).json({
resultCode: "S-1",
msg: "정성 피드백 및 상태 업데이트 성공",
});
} catch (error) {
await connection.rollback();
console.error("정성 피드백 업데이트 실패:", error.message);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
} finally {
connection.release();
}
};
const updateFeedbackStatus = async (req, res) => {
const { systemId } = req.body;
if (!systemId) {
return res.status(400).json({
resultCode: "F-1",
msg: "시스템 ID가 필요합니다.",
});
}
const query = `
UPDATE assessment_result
SET feedback_status = '전문가 자문이 반영되었습니다'
WHERE system_id = ?
`;
try {
const [result] = await pool.query(query, [systemId]);
console.log(`Feedback status updated:`, result);
if (result.affectedRows === 0) {
return res.status(404).json({
resultCode: "F-1",
msg: "해당 시스템 ID에 대한 결과를 찾을 수 없습니다.",
});
}
res.status(200).json({
resultCode: "S-1",
msg: "피드백 상태 업데이트 성공",
});
} catch (error) {
console.error("Error updating feedback status:", error.message);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
}
};
export {
getAssignedSystems,
getSystemAssessmentResult,
SystemsResult,
updateQuantitativeFeedback,
updateQualitativeFeedback,
updateFeedbackStatus,
};
1. getAssignedSystems 전문가가 배정된 시스템 목록 조회
const getAssignedSystems = async (req, res) => {
const { expertId } = req.query;
console.log("✅ [getAssignedSystems] Received expertId:", expertId);
if (!expertId) {
return res.status(400).json({
resultCode: "F-1",
msg: "전문가 ID가 필요합니다.",
});
}
try {
const query = `
SELECT s.id AS system_id, s.name AS system_name, u.institution_name,
ar.score, ar.grade, ar.feedback_status
FROM assignment a
JOIN systems s ON a.systems_id = s.id
JOIN User u ON s.user_id = u.id
LEFT JOIN assessment_result ar ON s.id = ar.system_id
WHERE a.expert_id = ?;
`;
console.log("🟡 [getAssignedSystems] Running query:", query);
const [results] = await pool.query(query, [expertId]);
console.log("✅ [getAssignedSystems] Query results:", results);
res.status(200).json({
resultCode: "S-1",
msg: "매칭된 시스템 조회 성공",
data: results,
});
} catch (error) {
console.error(
"❌ [getAssignedSystems] 배정된 시스템 조회 실패:",
error.message
);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
}
};
const query = `
SELECT s.id AS system_id, s.name AS system_name, u.institution_name,
ar.score, ar.grade, ar.feedback_status
FROM assignment a
JOIN systems s ON a.systems_id = s.id
JOIN User u ON s.user_id = u.id
LEFT JOIN assessment_result ar ON s.id = ar.system_id
WHERE a.expert_id = ?;
`;
전문가(expertId)가 배정된 시스템(assignment 테이블)을 조회.
결과에 시스템 이름, 기관 이름, 진단 결과(점수, 등급, 피드백 상태) 포함.
LEFT JOIN: assessment_result 데이터가 없어도 기본 시스템 정보를 반환.
LEFT JOIN이란?
두 개의 테이블을 연결할 때, 왼쪽 테이블(기준 테이블)에 있는 데이터를 모두 보여주고, 오른쪽 테이블의 일치하는 데이터만 추가로 가져오는 방식입니다.
2. getSystemAssessmentResult 특정 시스템의 자가진단 결과 조회
const getSystemAssessmentResult = async (req, res) => {
const { systemId } = req.query;
console.log("✅ [getSystemAssessmentResult] Received systemId:", systemId);
if (!systemId) {
return res.status(400).json({
resultCode: "F-1",
msg: "시스템 ID가 필요합니다.",
});
}
try {
const query = `
SELECT ar.id AS assessment_id, ar.system_id, ar.user_id, ar.score,
ar.grade, ar.feedback_status, ar.completed_at, u.institution_name
FROM assessment_result ar
JOIN systems s ON ar.system_id = s.id
JOIN User u ON s.user_id = u.id
WHERE ar.system_id = ?;
`;
console.log("🟡 [getSystemAssessmentResult] Running query:", query);
const [results] = await pool.query(query, [systemId]);
console.log("✅ [getSystemAssessmentResult] Query results:", results);
if (results.length === 0) {
console.warn(
"⚠️ [getSystemAssessmentResult] No results found for systemId:",
systemId
);
return res.status(404).json({
resultCode: "F-1",
msg: "자가진단 결과를 찾을 수 없습니다.",
});
}
res.status(200).json({
resultCode: "S-1",
msg: "자가진단 결과 조회 성공",
data: results[0],
});
} catch (error) {
console.error(
"❌ [getSystemAssessmentResult] 자가진단 결과 조회 실패:",
error.message
);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
}
};
const query = `
SELECT ar.id AS assessment_id, ar.system_id, ar.user_id, ar.score,
ar.grade, ar.feedback_status, ar.completed_at, u.institution_name
FROM assessment_result ar
JOIN systems s ON ar.system_id = s.id
JOIN User u ON s.user_id = u.id
WHERE ar.system_id = ?;
`;
JOIN systems s ON ar.system_id = s.id
systems 테이블과 조인: 자가진단 결과(assessment_result)의 system_id와 시스템 테이블의 id를 연결합니다
역할: 자가진단 결과가 어떤 시스템과 관련 있는지 가져옵니다.
ar.system_id = s.id
assessment_result.system_id와 systems.id가 같은 경우 데이터를 조인.
JOIN User u ON s.user_id = u.id
User 테이블과 조인:
systems 테이블의 user_id와 사용자 테이블의 id를 연결합니다.
역할: 시스템을 등록한 기관(사용자)의 정보를 가져옵니다.
s.user_id = u.id
systems.user_id와 User.id가 같은 경우 데이터를 조인.
3. updateQuantitativeFeedback, updateQualitativeFeedback
정량, 정성 피드백 업데이트
const updateQuantitativeFeedback = async (req, res) => {
const { systemId, feedbackResponses } = req.body;
if (!systemId || !Array.isArray(feedbackResponses)) {
console.error("Invalid data format:", { systemId, feedbackResponses });
return res.status(400).json({
resultCode: "F-1",
msg: "잘못된 요청 형식입니다. 'systemId' 및 'feedbackResponses'가 필요합니다.",
});
}
console.log("Received systemId:", systemId);
console.log("Received feedbackResponses:", feedbackResponses);
const connection = await pool.getConnection();
try {
const query = `
UPDATE quantitative
SET feedback = ?
WHERE question_number = ? AND system_id = ?
`;
await connection.beginTransaction();
// Update quantitative feedback
for (const { questionNumber, feedback } of feedbackResponses) {
if (typeof questionNumber !== "number" || typeof feedback !== "string") {
console.error("Invalid feedback response:", {
questionNumber,
feedback,
});
throw new Error("피드백 데이터 형식이 잘못되었습니다.");
}
await connection.query(query, [
feedback || "피드백 없음", // 기본값 설정
questionNumber,
systemId,
]);
}
console.log("Feedbacks updated successfully for system_id:", systemId);
// ✅ Update feedback status in `assessment_result`
const updateStatusQuery = `
UPDATE assessment_result
SET feedback_status = '전문가 자문이 반영되었습니다'
WHERE system_id = ?
`;
const [updateResult] = await connection.query(updateStatusQuery, [
systemId,
]);
console.log(
"Feedback status updated:",
updateResult.affectedRows,
"rows affected"
);
// Commit transaction
await connection.commit();
console.log("Transaction committed successfully");
res.status(200).json({
resultCode: "S-1",
msg: "정량 피드백 및 상태 업데이트 성공",
});
} catch (error) {
await connection.rollback();
console.error("Error updating feedback:", error.message);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
} finally {
connection.release();
}
};
/**
* 🔹 정성 피드백 업데이트
*/
const updateQualitativeFeedback = async (req, res) => {
const { systemId, feedbackResponses } = req.body;
if (!systemId || !feedbackResponses || !Array.isArray(feedbackResponses)) {
console.error("Invalid request data:", { systemId, feedbackResponses });
return res.status(400).json({
resultCode: "F-1",
msg: "잘못된 요청 형식입니다. 'systemId' 및 'feedbackResponses'가 필요합니다.",
});
}
const connection = await pool.getConnection();
try {
const query = `
UPDATE qualitative
SET feedback = ?, additional_comment = ?, response = ?
WHERE question_number = ? AND system_id = ?
`;
await connection.beginTransaction();
for (const response of feedbackResponses) {
const {
questionNumber,
feedback,
additionalComment,
response: userResponse,
} = response;
if (
typeof questionNumber !== "number" ||
typeof feedback !== "string" ||
typeof additionalComment !== "string" ||
typeof userResponse !== "string"
) {
console.error("Invalid feedback response:", response);
throw new Error("피드백 데이터 형식이 잘못되었습니다.");
}
await connection.query(query, [
feedback,
additionalComment,
userResponse,
questionNumber,
systemId,
]);
}
console.log("Feedbacks updated successfully for system_id:", systemId);
// ✅ 전문가 자문 상태 업데이트
const updateStatusQuery = `
UPDATE assessment_result
SET feedback_status = '전문가 자문이 반영되었습니다'
WHERE system_id = ?
`;
const [updateResult] = await connection.query(updateStatusQuery, [
systemId,
]);
console.log(
"Feedback status updated:",
updateResult.affectedRows,
"rows affected"
);
await connection.commit();
console.log("Transaction committed successfully");
res.status(200).json({
resultCode: "S-1",
msg: "정성 피드백 및 상태 업데이트 성공",
});
} catch (error) {
await connection.rollback();
console.error("정성 피드백 업데이트 실패:", error.message);
res.status(500).json({
resultCode: "F-1",
msg: "서버 오류 발생",
error: error.message,
});
} finally {
connection.release();
}
};
const query = `
UPDATE quantitative
SET feedback = ?
WHERE question_number = ? AND system_id = ?
`;
UPDATE 문: quantitative 테이블에서 question_number와 system_id를 기준으로 feedback 값을 업데이트.
const connection = await pool.getConnection();
await connection.beginTransaction();
for (const { questionNumber, feedback } of feedbackResponses) {
if (typeof questionNumber !== "number" || typeof feedback !== "string") {
console.error("Invalid feedback response:", {
questionNumber,
feedback,
});
throw new Error("피드백 데이터 형식이 잘못되었습니다.");
}
await connection.query(query, [
feedback || "피드백 없음", // 기본값 설정
questionNumber,
systemId,
]);
}
await connection.commit();
connection.release();
const connection = await pool.getConnection();
await connection.beginTransaction();
connection: pool.getConnection()을 호출해 데이터베이스와의 연결을 생성.
여러 작업(쿼리)을 묶어서 처리하기 위해 연결 객체를 사용.
beginTransaction(): 트랜잭션을 시작.
트랜잭션은 데이터베이스 작업을 하나의 묶음으로 처리하는 기능입니다.
이 트랜잭션이 끝나기 전까지 데이터베이스 변경 사항은 다른 사용자에게 보이지 않습니다.
목적: 모든 작업이 성공했을 때만 데이터베이스에 변경 사항을 적용(커밋) 합니다
하나라도 실패하면 이전 변경 사항을 롤백하여 데이터 일관성을 보장합니다.
for (const { questionNumber, feedback } of feedbackResponses) {
if (typeof questionNumber !== "number" || typeof feedback !== "string") {
console.error("Invalid feedback response:", {
questionNumber,
feedback,
});
throw new Error("피드백 데이터 형식이 잘못되었습니다.");
}
await connection.query(query, [
feedback || "피드백 없음", // 기본값 설정
questionNumber,
systemId,
]);
}
for문으로 feedbackResponses 배열을 순회 합니다.
if (typeof questionNumber !== "number" || typeof feedback !== "string") {
console.error("Invalid feedback response:", {
questionNumber,
feedback,
});
throw new Error("피드백 데이터 형식이 잘못되었습니다.");
}
각 questionNumber와 feedback 값이 예상된 타입인지 확인합니다.
questionNumber: 숫자여야 합니다
feedback: 문자열이어야 합니다.
유효하지 않은 데이터가 발견되면 오류를 출력하고 예외(throw new Error)를 발생시켜 트랜잭션을 중단합니다.
정량과 정성 비슷한 구조로 되어있어서 이해가 될겁니다.
마지막으로
6. updateFeedbackStatus 피드백 상태 업데이트
const query = `
UPDATE assessment_result
SET feedback_status = '전문가 자문이 반영되었습니다'
WHERE system_id = ?;
`;
특정 system_id에 대한 피드백 상태를 업데이트 합니다.
'프로젝트' 카테고리의 다른 글
개인정보-컴플라이언스-웹애플리케이션(10) - (시스템) 프론트 코드 (0) | 2025.01.28 |
---|---|
개인정보-컴플라이언스-웹애플리케이션(9) - (회원가입 로그인) 프론트 코드 (0) | 2025.01.28 |
개인정보-컴플라이언스-웹애플리케이션(7) - (자가진단 설문 결과) 백엔드 코드 (0) | 2025.01.26 |
개인정보-컴플라이언스-웹애플리케이션(6) - (자가진단 설문) 백엔드 코드 (0) | 2025.01.26 |
개인정보-컴플라이언스-웹애플리케이션(5) - (시스템) 백엔드 코드 (0) | 2025.01.24 |