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:
Hyungi Ahn
2026-02-03 09:31:26 +09:00
parent 4b158de1eb
commit c42c9f4fa3
29 changed files with 7042 additions and 809 deletions

View File

@@ -0,0 +1,43 @@
/**
* 작업보고서 부적합에 카테고리/아이템 컬럼 추가
*
* 변경사항:
* 1. work_report_defects 테이블에 category_id, item_id 컬럼 추가
* 2. issue_report_categories, issue_report_items 테이블 참조
*/
exports.up = function(knex) {
return knex.schema
.alterTable('work_report_defects', function(table) {
// 카테고리 ID 추가
table.integer('category_id').unsigned().nullable()
.comment('issue_report_categories의 category_id (직접 입력 시)')
.after('issue_report_id');
// 아이템 ID 추가
table.integer('item_id').unsigned().nullable()
.comment('issue_report_items의 item_id (직접 입력 시)')
.after('category_id');
// 외래키 추가
table.foreign('category_id')
.references('category_id')
.inTable('issue_report_categories')
.onDelete('SET NULL');
table.foreign('item_id')
.references('item_id')
.inTable('issue_report_items')
.onDelete('SET NULL');
});
};
exports.down = function(knex) {
return knex.schema
.alterTable('work_report_defects', function(table) {
table.dropForeign('category_id');
table.dropForeign('item_id');
table.dropColumn('category_id');
table.dropColumn('item_id');
});
};

View File

@@ -0,0 +1,85 @@
/**
* 작업보고서 부적합을 신고 시스템과 연동
*
* 변경사항:
* 1. work_report_defects 테이블에 issue_report_id 컬럼 추가
* 2. error_type_id를 NULL 허용으로 변경 (신고 연동 시 불필요)
* 3. work_issue_reports.report_id (unsigned int)와 타입 일치 필요
*/
exports.up = function(knex) {
return knex.schema
.alterTable('work_report_defects', function(table) {
// 1. issue_report_id 컬럼 추가 (unsigned int로 work_issue_reports.report_id와 타입 일치)
table.integer('issue_report_id').unsigned().nullable()
.comment('work_issue_reports의 report_id (신고된 이슈 연결)')
.after('error_type_id');
// 2. 외래키 추가 (work_issue_reports.report_id 참조)
table.foreign('issue_report_id')
.references('report_id')
.inTable('work_issue_reports')
.onDelete('SET NULL');
// 3. 인덱스 추가
table.index('issue_report_id');
})
// 4. error_type_id를 NULL 허용으로 변경
.then(function() {
return knex.raw(`
ALTER TABLE work_report_defects
MODIFY COLUMN error_type_id INT NULL
COMMENT 'error_types의 id (부적합 원인) - 레거시, issue_report_id 사용 권장'
`);
})
// 5. 유니크 제약 수정 (issue_report_id도 고려)
.then(function() {
// 기존 유니크 제약 삭제
return knex.raw(`
ALTER TABLE work_report_defects
DROP INDEX work_report_defects_report_id_error_type_id_unique
`).catch(() => {
// 인덱스가 없을 수 있음 - 무시
});
})
.then(function() {
// 새 유니크 제약 추가 (report_id + issue_report_id 조합)
return knex.raw(`
ALTER TABLE work_report_defects
ADD UNIQUE INDEX work_report_defects_report_issue_unique (report_id, issue_report_id)
`).catch(() => {
// 이미 존재할 수 있음 - 무시
});
});
};
exports.down = function(knex) {
return knex.schema
.alterTable('work_report_defects', function(table) {
// 외래키 및 인덱스 삭제
table.dropForeign('issue_report_id');
table.dropIndex('issue_report_id');
table.dropColumn('issue_report_id');
})
// error_type_id를 다시 NOT NULL로 변경
.then(function() {
return knex.raw(`
ALTER TABLE work_report_defects
MODIFY COLUMN error_type_id INT NOT NULL
COMMENT 'error_types의 id (부적합 원인)'
`);
})
// 기존 유니크 제약 복원
.then(function() {
return knex.raw(`
ALTER TABLE work_report_defects
DROP INDEX IF EXISTS work_report_defects_report_issue_unique
`).catch(() => {});
})
.then(function() {
return knex.raw(`
ALTER TABLE work_report_defects
ADD UNIQUE INDEX work_report_defects_report_id_error_type_id_unique (report_id, error_type_id)
`).catch(() => {});
});
};