fix: 부적합 제출 버그 수정 및 UI 개선
- 부적합 API 호출 형식 수정 (카테고리/아이템 추가 시) - 부적합 저장 시 내부 플래그 제거 후 백엔드 전송 - 기본 부적합 객체 구조 수정 (category_id, item_id 추가) - 날씨 API 시간대 수정 (UTC → KST 변환) - 신고 카테고리 관리 페이지 추가 (/pages/admin/issue-categories.html) - 부적합 입력 UI 개선 (대분류→소분류 캐스케이딩 선택) - 저장된 부적합 분리 표시 및 수정/삭제 기능 - 디버깅 로그 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -274,6 +274,7 @@ const getSummaryService = async (year, month) => {
|
||||
|
||||
/**
|
||||
* 작업 보고서의 부적합 원인 목록 조회
|
||||
* - error_type_id 또는 issue_report_id 중 하나로 연결
|
||||
*/
|
||||
const getReportDefectsService = async (reportId) => {
|
||||
const db = await getDb();
|
||||
@@ -283,13 +284,22 @@ const getReportDefectsService = async (reportId) => {
|
||||
d.defect_id,
|
||||
d.report_id,
|
||||
d.error_type_id,
|
||||
d.issue_report_id,
|
||||
d.defect_hours,
|
||||
d.note,
|
||||
d.created_at,
|
||||
et.name as error_type_name,
|
||||
et.severity
|
||||
et.severity as error_severity,
|
||||
ir.content as issue_content,
|
||||
ir.status as issue_status,
|
||||
irc.category_name as issue_category_name,
|
||||
irc.severity as issue_severity,
|
||||
iri.item_name as issue_item_name
|
||||
FROM work_report_defects d
|
||||
JOIN error_types et ON d.error_type_id = et.id
|
||||
LEFT JOIN error_types et ON d.error_type_id = et.id
|
||||
LEFT JOIN work_issue_reports ir ON d.issue_report_id = ir.report_id
|
||||
LEFT JOIN issue_report_categories irc ON ir.category_id = irc.category_id
|
||||
LEFT JOIN issue_report_items iri ON ir.item_id = iri.item_id
|
||||
WHERE d.report_id = ?
|
||||
ORDER BY d.created_at
|
||||
`, [reportId]);
|
||||
@@ -303,6 +313,9 @@ const getReportDefectsService = async (reportId) => {
|
||||
|
||||
/**
|
||||
* 부적합 원인 저장 (전체 교체)
|
||||
* - error_type_id 또는 issue_report_id 중 하나 사용 가능
|
||||
* - issue_report_id: 신고된 이슈와 연결
|
||||
* - error_type_id: 기존 오류 유형 (레거시)
|
||||
*/
|
||||
const saveReportDefectsService = async (reportId, defects) => {
|
||||
const db = await getDb();
|
||||
@@ -315,10 +328,19 @@ const saveReportDefectsService = async (reportId, defects) => {
|
||||
// 새 부적합 원인 추가
|
||||
if (defects && defects.length > 0) {
|
||||
for (const defect of defects) {
|
||||
// issue_report_id > category_id/item_id > error_type_id 순으로 우선
|
||||
await db.execute(`
|
||||
INSERT INTO work_report_defects (report_id, error_type_id, defect_hours, note)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`, [reportId, defect.error_type_id, defect.defect_hours || 0, defect.note || null]);
|
||||
INSERT INTO work_report_defects (report_id, error_type_id, issue_report_id, category_id, item_id, defect_hours, note)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
`, [
|
||||
reportId,
|
||||
(defect.issue_report_id || defect.category_id) ? null : (defect.error_type_id || null),
|
||||
defect.issue_report_id || null,
|
||||
defect.category_id || null,
|
||||
defect.item_id || null,
|
||||
defect.defect_hours || 0,
|
||||
defect.note || null
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,6 +349,11 @@ const saveReportDefectsService = async (reportId, defects) => {
|
||||
? defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0)
|
||||
: 0;
|
||||
|
||||
// 첫 번째 defect의 error_type_id를 대표값으로 (레거시 호환)
|
||||
const firstErrorTypeId = defects && defects.length > 0
|
||||
? (defects.find(d => d.error_type_id)?.error_type_id || null)
|
||||
: null;
|
||||
|
||||
await db.execute(`
|
||||
UPDATE daily_work_reports
|
||||
SET error_hours = ?,
|
||||
@@ -335,7 +362,7 @@ const saveReportDefectsService = async (reportId, defects) => {
|
||||
WHERE id = ?
|
||||
`, [
|
||||
totalErrorHours,
|
||||
defects && defects.length > 0 ? defects[0].error_type_id : null,
|
||||
firstErrorTypeId,
|
||||
totalErrorHours > 0 ? 2 : 1,
|
||||
reportId
|
||||
]);
|
||||
@@ -353,14 +380,21 @@ const saveReportDefectsService = async (reportId, defects) => {
|
||||
|
||||
/**
|
||||
* 부적합 원인 추가 (단일)
|
||||
* - issue_report_id 또는 error_type_id 중 하나 사용
|
||||
*/
|
||||
const addReportDefectService = async (reportId, defectData) => {
|
||||
const db = await getDb();
|
||||
try {
|
||||
const [result] = await db.execute(`
|
||||
INSERT INTO work_report_defects (report_id, error_type_id, defect_hours, note)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`, [reportId, defectData.error_type_id, defectData.defect_hours || 0, defectData.note || null]);
|
||||
INSERT INTO work_report_defects (report_id, error_type_id, issue_report_id, defect_hours, note)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`, [
|
||||
reportId,
|
||||
defectData.issue_report_id ? null : (defectData.error_type_id || null),
|
||||
defectData.issue_report_id || null,
|
||||
defectData.defect_hours || 0,
|
||||
defectData.note || null
|
||||
]);
|
||||
|
||||
// 총 부적합 시간 업데이트
|
||||
await updateTotalErrorHours(reportId);
|
||||
@@ -404,6 +438,7 @@ const removeReportDefectService = async (defectId) => {
|
||||
|
||||
/**
|
||||
* 총 부적합 시간 업데이트 헬퍼
|
||||
* - issue_report_id가 있는 경우도 고려
|
||||
*/
|
||||
const updateTotalErrorHours = async (reportId) => {
|
||||
const db = await getDb();
|
||||
@@ -415,9 +450,12 @@ const updateTotalErrorHours = async (reportId) => {
|
||||
|
||||
const totalErrorHours = result[0].total || 0;
|
||||
|
||||
// 첫 번째 부적합 원인의 error_type_id를 대표값으로 사용
|
||||
// 첫 번째 부적합 원인의 error_type_id를 대표값으로 사용 (레거시 호환)
|
||||
// issue_report_id만 있는 경우 error_type_id는 null
|
||||
const [firstDefect] = await db.execute(`
|
||||
SELECT error_type_id FROM work_report_defects WHERE report_id = ? ORDER BY created_at LIMIT 1
|
||||
SELECT error_type_id FROM work_report_defects
|
||||
WHERE report_id = ? AND error_type_id IS NOT NULL
|
||||
ORDER BY created_at LIMIT 1
|
||||
`, [reportId]);
|
||||
|
||||
await db.execute(`
|
||||
|
||||
Reference in New Issue
Block a user