fix(tkfb): project_code → job_no 컬럼명 수정 (500 에러 해결)

projects 테이블에 project_code 컬럼이 없고 job_no가 올바른 컬럼명.
백엔드 SQL에서는 pr.job_no AS project_code alias 사용,
프론트 드롭다운에서는 p.job_no로 직접 참조.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-17 08:18:49 +09:00
parent adf3a197fd
commit 184cdd6aa8
4 changed files with 13 additions and 13 deletions

View File

@@ -57,7 +57,7 @@ const MeetingModel = {
// 안건
const [items] = await db.query(`
SELECT ai.*, pr.project_name, pr.project_code,
SELECT ai.*, pr.project_name, pr.job_no AS project_code,
ms.milestone_name, ms.milestone_date,
su.name AS responsible_name
FROM meeting_agenda_items ai
@@ -185,7 +185,7 @@ const MeetingModel = {
const db = await getDb();
let sql = `
SELECT ai.*, m.title AS meeting_title, m.meeting_date,
pr.project_name, pr.project_code,
pr.project_name, pr.job_no AS project_code,
su.name AS responsible_name
FROM meeting_agenda_items ai
JOIN meeting_minutes m ON ai.meeting_id = m.meeting_id

View File

@@ -48,7 +48,7 @@ const ScheduleModel = {
async getEntries(filters = {}) {
const db = await getDb();
let sql = `
SELECT e.*, p.phase_name, p.color AS phase_color, pr.project_name, pr.project_code,
SELECT e.*, p.phase_name, p.color AS phase_color, pr.project_name, pr.job_no AS project_code,
su.name AS created_by_name
FROM schedule_entries e
JOIN schedule_phases p ON e.phase_id = p.phase_id
@@ -66,7 +66,7 @@ const ScheduleModel = {
sql += ' AND ((YEAR(e.start_date) = ? AND MONTH(e.start_date) = ?) OR (YEAR(e.end_date) = ? AND MONTH(e.end_date) = ?))';
params.push(filters.year, filters.month, filters.year, filters.month);
}
sql += ' ORDER BY pr.project_code, p.display_order, e.display_order';
sql += ' ORDER BY pr.job_no, p.display_order, e.display_order';
const [rows] = await db.query(sql, params);
return rows;
},
@@ -76,13 +76,13 @@ const ScheduleModel = {
// 해당 연도에 걸치는 모든 항목
const [entries] = await db.query(`
SELECT e.*, p.phase_name, p.color AS phase_color, p.display_order AS phase_order,
pr.project_name, pr.project_code
pr.project_name, pr.job_no AS project_code
FROM schedule_entries e
JOIN schedule_phases p ON e.phase_id = p.phase_id
JOIN projects pr ON e.project_id = pr.project_id
WHERE (YEAR(e.start_date) <= ? AND YEAR(e.end_date) >= ?)
AND e.status != 'cancelled'
ORDER BY pr.project_code, p.display_order, e.display_order
ORDER BY pr.job_no, p.display_order, e.display_order
`, [year, year]);
// 의존관계
@@ -98,7 +98,7 @@ const ScheduleModel = {
// 마일스톤
const [milestones] = await db.query(`
SELECT m.*, pr.project_name, pr.project_code
SELECT m.*, pr.project_name, pr.job_no AS project_code
FROM schedule_milestones m
JOIN projects pr ON m.project_id = pr.project_id
WHERE YEAR(m.milestone_date) = ?
@@ -200,7 +200,7 @@ const ScheduleModel = {
async getMilestones(filters = {}) {
const db = await getDb();
let sql = `
SELECT m.*, pr.project_name, pr.project_code, e.task_name AS entry_task_name,
SELECT m.*, pr.project_name, pr.job_no AS project_code, e.task_name AS entry_task_name,
su.name AS created_by_name
FROM schedule_milestones m
JOIN projects pr ON m.project_id = pr.project_id

View File

@@ -35,7 +35,7 @@ document.addEventListener('DOMContentLoaded', async () => {
// Populate project select in item modal
const projSel = document.getElementById('itemProject');
projects.forEach(p => {
projSel.innerHTML += `<option value="${p.project_id}">${escapeHtml(p.project_code)} ${escapeHtml(p.project_name)}</option>`;
projSel.innerHTML += `<option value="${p.project_id}">${escapeHtml(p.job_no)} ${escapeHtml(p.project_name)}</option>`;
});
// Populate responsible user select

View File

@@ -374,7 +374,7 @@ function showMilestoneDetail(milestoneId) {
function showNcPopup(projectId) {
const list = ncCache[projectId] || [];
const proj = projects.find(p => p.project_id === projectId);
document.getElementById('ncPopupTitle').textContent = `부적합 현황 - ${proj ? proj.project_code : ''}`;
document.getElementById('ncPopupTitle').textContent = `부적합 현황 - ${proj ? proj.job_no : ''}`;
const statusLabels = { reported: '신고', received: '접수', reviewing: '검토중', in_progress: '처리중', completed: '완료' };
let html = '';
if (list.length === 0) {
@@ -402,7 +402,7 @@ function openEntryModal(editId) {
document.getElementById('entryModalTitle').textContent = isEdit ? '공정표 항목 수정' : '공정표 항목 추가';
// Populate dropdowns
populateSelect('entryProject', projects, 'project_id', p => `${p.project_code} ${p.project_name}`);
populateSelect('entryProject', projects, 'project_id', p => `${p.job_no} ${p.project_name}`);
populateSelect('entryPhase', phases, 'phase_id', p => p.phase_name);
// Template select (populated on phase change)
@@ -530,7 +530,7 @@ async function saveEntry() {
/* ===== Batch Modal ===== */
function openBatchModal() {
populateSelect('batchProject', projects, 'project_id', p => `${p.project_code} ${p.project_name}`);
populateSelect('batchProject', projects, 'project_id', p => `${p.job_no} ${p.project_name}`);
populateSelect('batchPhase', phases, 'phase_id', p => p.phase_name);
document.getElementById('batchStartDate').value = '';
document.getElementById('batchTemplateList').innerHTML = '';
@@ -610,7 +610,7 @@ function openMilestoneModal(editId) {
const isEdit = !!editId;
document.getElementById('milestoneModalTitle').textContent = isEdit ? '마일스톤 수정' : '마일스톤 추가';
populateSelect('milestoneProject', projects, 'project_id', p => `${p.project_code} ${p.project_name}`);
populateSelect('milestoneProject', projects, 'project_id', p => `${p.job_no} ${p.project_name}`);
if (isEdit) {
const m = ganttData.milestones.find(ms => ms.milestone_id === editId);