fix(purchase): 작업일정 삭제 시 관련 데이터 캐스케이드 삭제 (admin 전용)

- 삭제 권한을 admin 전용으로 변경 (requireAdmin)
- 트랜잭션으로 reports → checkins → safety_education → schedule 순서 삭제
- 프론트엔드: admin만 삭제 버튼 표시, 종속 데이터 삭제 경고 추가
- 404 처리 및 한국어 에러 메시지

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-13 21:03:27 +09:00
parent 3e50639914
commit e8076a8550
4 changed files with 30 additions and 9 deletions

View File

@@ -77,6 +77,7 @@ function renderScheduleTable(list, total) {
tbody.innerHTML = list.map(s => {
const [cls, label] = statusMap[s.status] || ['badge-gray', s.status];
const isAdmin = currentUser && (currentUser.role === 'admin' || currentUser.role === 'system');
const canEdit = s.status === 'scheduled';
const isRequest = s.status === 'requested';
const projectLabel = s.project_name ? (s.job_no ? `[${s.job_no}] ${s.project_name}` : s.project_name) : '';
@@ -91,8 +92,8 @@ function renderScheduleTable(list, total) {
<td class="text-right">
${isRequest ? `<button onclick="openApproveModal(${s.id})" class="text-amber-600 hover:text-amber-800 text-xs mr-1 font-medium" title="승인/반려"><i class="fas fa-check-circle mr-1"></i>처리</button>` : ''}
${(s.status === 'in_progress' || s.status === 'completed') ? `<button onclick="viewCheckins(${s.id})" class="text-emerald-600 hover:text-emerald-800 text-xs mr-1" title="체크인 현황"><i class="fas fa-clipboard-check"></i></button>` : ''}
${canEdit ? `<button onclick="openEditSchedule(${s.id})" class="text-blue-600 hover:text-blue-800 text-xs mr-1" title="수정"><i class="fas fa-edit"></i></button>
<button onclick="deleteSchedule(${s.id})" class="text-red-500 hover:text-red-700 text-xs" title="삭제"><i class="fas fa-trash"></i></button>` : ''}
${canEdit ? `<button onclick="openEditSchedule(${s.id})" class="text-blue-600 hover:text-blue-800 text-xs mr-1" title="수정"><i class="fas fa-edit"></i></button>` : ''}
${isAdmin ? `<button onclick="deleteSchedule(${s.id})" class="text-red-500 hover:text-red-700 text-xs" title="삭제"><i class="fas fa-trash"></i></button>` : ''}
</td>
</tr>`;
}).join('');
@@ -285,7 +286,7 @@ async function submitEditSchedule(e) {
/* ===== Delete Schedule ===== */
async function deleteSchedule(id) {
if (!confirm('이 일정을 삭제하시겠습니까?')) return;
if (!confirm('이 일정을 삭제하시겠습니까?\n\n⚠ 관련 체크인·작업보고서·안전교육 기록이 모두 삭제됩니다.')) return;
try {
await api('/schedules/' + id, { method: 'DELETE' });
showToast('일정이 삭제되었습니다');