feat: 안전 코드 tksafety 이관 + 사용자 관리 정리 + UI Tailwind 전환
Phase 1: tksafety에 출입신청/체크리스트 API·웹 추가, tkfb 안전 코드 삭제
Phase 2: 사용자 관리 페이지 삭제, API 축소, 알림 수신자 tkuser 이관
Phase 3: tkuser 권한 페이지 정의 업데이트
Phase 4: 전체 34개 페이지 Tailwind CSS + tkfb-core.js 전환,
미사용 CSS 20개·인프라 JS 10개·템플릿·컴포넌트 삭제
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -110,8 +110,8 @@ async function update(req, res) {
|
||||
return res.status(403).json({ success: false, error: '본인이 작성한 보고만 수정할 수 있습니다' });
|
||||
}
|
||||
|
||||
// 확인 완료된 보고 수정 불가
|
||||
if (existing.confirmed_by) {
|
||||
// 확인 완료된 보고 수정 불가 (협력업체만 제한, 구매팀은 수정 가능)
|
||||
if (req.user.partner_company_id && existing.confirmed_by) {
|
||||
return res.status(400).json({ success: false, error: '확인 완료된 보고는 수정할 수 없습니다' });
|
||||
}
|
||||
|
||||
@@ -136,6 +136,32 @@ async function confirm(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
// 작업보고 반려
|
||||
async function reject(req, res) {
|
||||
try {
|
||||
const existing = await workReportModel.findById(req.params.id);
|
||||
if (!existing) {
|
||||
return res.status(404).json({ success: false, error: '작업보고를 찾을 수 없습니다' });
|
||||
}
|
||||
if (existing.confirmed_by) {
|
||||
return res.status(400).json({ success: false, error: '확인된 보고는 반려할 수 없습니다. 먼저 확인 취소하세요' });
|
||||
}
|
||||
if (existing.rejected_by) {
|
||||
return res.status(400).json({ success: false, error: '이미 반려된 보고입니다' });
|
||||
}
|
||||
const { reason } = req.body;
|
||||
if (!reason || !reason.trim()) {
|
||||
return res.status(400).json({ success: false, error: '반려 사유를 입력하세요' });
|
||||
}
|
||||
const rejectedBy = req.user.user_id || req.user.id;
|
||||
const row = await workReportModel.reject(req.params.id, rejectedBy, reason.trim());
|
||||
res.json({ success: true, data: row });
|
||||
} catch (err) {
|
||||
console.error('WorkReport reject error:', err);
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
}
|
||||
|
||||
// 종합 요약
|
||||
async function summary(req, res) {
|
||||
try {
|
||||
@@ -252,4 +278,47 @@ async function exportExcel(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { list, getById, myReports, create, update, confirm, summary, exportExcel };
|
||||
// 작업보고 삭제
|
||||
async function deleteReport(req, res) {
|
||||
try {
|
||||
const existing = await workReportModel.findById(req.params.id);
|
||||
if (!existing) {
|
||||
return res.status(404).json({ success: false, error: '작업보고를 찾을 수 없습니다' });
|
||||
}
|
||||
const checkinId = existing.checkin_id;
|
||||
await workReportModel.deleteReport(req.params.id);
|
||||
|
||||
// 남은 보고가 0건이면 체크아웃 되돌리기
|
||||
if (checkinId) {
|
||||
const remaining = await workReportModel.countByCheckin(checkinId);
|
||||
if (remaining === 0) {
|
||||
await checkinModel.resetCheckout(checkinId);
|
||||
}
|
||||
}
|
||||
|
||||
res.json({ success: true, message: '삭제되었습니다' });
|
||||
} catch (err) {
|
||||
console.error('WorkReport delete error:', err);
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
}
|
||||
|
||||
// 확인 취소
|
||||
async function unconfirm(req, res) {
|
||||
try {
|
||||
const existing = await workReportModel.findById(req.params.id);
|
||||
if (!existing) {
|
||||
return res.status(404).json({ success: false, error: '작업보고를 찾을 수 없습니다' });
|
||||
}
|
||||
if (!existing.confirmed_by) {
|
||||
return res.status(400).json({ success: false, error: '이미 미확인 상태입니다' });
|
||||
}
|
||||
const row = await workReportModel.unconfirm(req.params.id);
|
||||
res.json({ success: true, data: row });
|
||||
} catch (err) {
|
||||
console.error('WorkReport unconfirm error:', err);
|
||||
res.status(500).json({ success: false, error: err.message });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { list, getById, myReports, create, update, confirm, reject, deleteReport, unconfirm, summary, exportExcel };
|
||||
|
||||
Reference in New Issue
Block a user