Files
TK-FB-Project/api.hyungi.net/controllers/patrolController.js
Hyungi Ahn 90d3e32992 feat: 일일순회점검 시스템 구축 및 관리 기능 개선
- 일일순회점검 시스템 신규 구현
  - DB 테이블: patrol_checklist_items, daily_patrol_sessions, patrol_check_records, workplace_items, item_types
  - API: /api/patrol/* 엔드포인트
  - 프론트엔드: 지도 기반 작업장 점검 UI

- 설비 관리 기능 개선
  - 구매 관련 필드 추가 (구매일, 가격, 공급업체 등)
  - 설비 코드 자동 생성 (TKP-XXX 형식)

- 작업장 관리 개선
  - 레이아웃 이미지 업로드 기능
  - 마커 위치 저장 기능

- 부서 관리 기능 추가
- 사이드바 네비게이션 카테고리 재구성
- 이미지 401 오류 수정 (정적 파일 경로 처리)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:41:41 +09:00

296 lines
10 KiB
JavaScript

// patrolController.js
// 일일순회점검 시스템 컨트롤러
const PatrolModel = require('../models/patrolModel');
const PatrolController = {
// ==================== 순회점검 세션 ====================
// 세션 시작/조회
getOrCreateSession: async (req, res) => {
try {
const { patrol_date, patrol_time, category_id } = req.body;
const inspectorId = req.user.user_id;
if (!patrol_date || !patrol_time || !category_id) {
return res.status(400).json({ success: false, message: '필수 정보가 누락되었습니다.' });
}
const session = await PatrolModel.getOrCreateSession(patrol_date, patrol_time, category_id, inspectorId);
res.json({ success: true, data: session });
} catch (error) {
console.error('세션 생성/조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 세션 상세 조회
getSession: async (req, res) => {
try {
const { sessionId } = req.params;
const session = await PatrolModel.getSession(sessionId);
if (!session) {
return res.status(404).json({ success: false, message: '세션을 찾을 수 없습니다.' });
}
res.json({ success: true, data: session });
} catch (error) {
console.error('세션 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 세션 목록 조회
getSessions: async (req, res) => {
try {
const { patrol_date, patrol_time, category_id, status, limit } = req.query;
const sessions = await PatrolModel.getSessions({
patrol_date,
patrol_time,
category_id,
status,
limit
});
res.json({ success: true, data: sessions });
} catch (error) {
console.error('세션 목록 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 세션 완료
completeSession: async (req, res) => {
try {
const { sessionId } = req.params;
await PatrolModel.completeSession(sessionId);
res.json({ success: true, message: '순회점검이 완료되었습니다.' });
} catch (error) {
console.error('세션 완료 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 세션 메모 업데이트
updateSessionNotes: async (req, res) => {
try {
const { sessionId } = req.params;
const { notes } = req.body;
await PatrolModel.updateSessionNotes(sessionId, notes);
res.json({ success: true, message: '메모가 저장되었습니다.' });
} catch (error) {
console.error('메모 저장 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// ==================== 체크리스트 항목 ====================
// 체크리스트 항목 조회
getChecklistItems: async (req, res) => {
try {
const { category_id, workplace_id } = req.query;
const items = await PatrolModel.getChecklistItems(category_id, workplace_id);
// 카테고리별로 그룹화
const grouped = {};
items.forEach(item => {
if (!grouped[item.check_category]) {
grouped[item.check_category] = [];
}
grouped[item.check_category].push(item);
});
res.json({ success: true, data: { items, grouped } });
} catch (error) {
console.error('체크리스트 항목 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 체크리스트 항목 추가
createChecklistItem: async (req, res) => {
try {
const itemId = await PatrolModel.createChecklistItem(req.body);
res.json({ success: true, data: { item_id: itemId }, message: '항목이 추가되었습니다.' });
} catch (error) {
console.error('항목 추가 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 체크리스트 항목 수정
updateChecklistItem: async (req, res) => {
try {
const { itemId } = req.params;
await PatrolModel.updateChecklistItem(itemId, req.body);
res.json({ success: true, message: '항목이 수정되었습니다.' });
} catch (error) {
console.error('항목 수정 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 체크리스트 항목 삭제
deleteChecklistItem: async (req, res) => {
try {
const { itemId } = req.params;
await PatrolModel.deleteChecklistItem(itemId);
res.json({ success: true, message: '항목이 삭제되었습니다.' });
} catch (error) {
console.error('항목 삭제 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// ==================== 체크 기록 ====================
// 작업장별 체크 기록 조회
getCheckRecords: async (req, res) => {
try {
const { sessionId } = req.params;
const { workplace_id } = req.query;
const records = await PatrolModel.getCheckRecords(sessionId, workplace_id);
res.json({ success: true, data: records });
} catch (error) {
console.error('체크 기록 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 체크 기록 저장
saveCheckRecord: async (req, res) => {
try {
const { sessionId } = req.params;
const { workplace_id, check_item_id, is_checked, check_result, note } = req.body;
if (!workplace_id || !check_item_id) {
return res.status(400).json({ success: false, message: '필수 정보가 누락되었습니다.' });
}
await PatrolModel.saveCheckRecord(sessionId, workplace_id, check_item_id, is_checked, check_result, note);
res.json({ success: true, message: '저장되었습니다.' });
} catch (error) {
console.error('체크 기록 저장 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 체크 기록 일괄 저장
saveCheckRecords: async (req, res) => {
try {
const { sessionId } = req.params;
const { workplace_id, records } = req.body;
if (!workplace_id || !records || !Array.isArray(records)) {
return res.status(400).json({ success: false, message: '필수 정보가 누락되었습니다.' });
}
await PatrolModel.saveCheckRecords(sessionId, workplace_id, records);
res.json({ success: true, message: '저장되었습니다.' });
} catch (error) {
console.error('체크 기록 일괄 저장 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// ==================== 작업장 물품 현황 ====================
// 작업장 물품 조회
getWorkplaceItems: async (req, res) => {
try {
const { workplaceId } = req.params;
const { include_inactive } = req.query;
const items = await PatrolModel.getWorkplaceItems(workplaceId, include_inactive !== 'true');
res.json({ success: true, data: items });
} catch (error) {
console.error('물품 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 물품 추가
createWorkplaceItem: async (req, res) => {
try {
const { workplaceId } = req.params;
const data = { ...req.body, workplace_id: workplaceId, created_by: req.user.user_id };
const itemId = await PatrolModel.createWorkplaceItem(data);
res.json({ success: true, data: { item_id: itemId }, message: '물품이 추가되었습니다.' });
} catch (error) {
console.error('물품 추가 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 물품 수정
updateWorkplaceItem: async (req, res) => {
try {
const { itemId } = req.params;
await PatrolModel.updateWorkplaceItem(itemId, req.body, req.user.user_id);
res.json({ success: true, message: '물품이 수정되었습니다.' });
} catch (error) {
console.error('물품 수정 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 물품 삭제
deleteWorkplaceItem: async (req, res) => {
try {
const { itemId } = req.params;
const { permanent } = req.query;
if (permanent === 'true') {
await PatrolModel.hardDeleteWorkplaceItem(itemId);
} else {
await PatrolModel.deleteWorkplaceItem(itemId, req.user.user_id);
}
res.json({ success: true, message: '물품이 삭제되었습니다.' });
} catch (error) {
console.error('물품 삭제 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// ==================== 물품 유형 ====================
// 물품 유형 목록
getItemTypes: async (req, res) => {
try {
const types = await PatrolModel.getItemTypes();
res.json({ success: true, data: types });
} catch (error) {
console.error('물품 유형 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// ==================== 대시보드/통계 ====================
// 오늘 순회점검 현황
getTodayStatus: async (req, res) => {
try {
const { category_id } = req.query;
const status = await PatrolModel.getTodayPatrolStatus(category_id);
res.json({ success: true, data: status });
} catch (error) {
console.error('오늘 현황 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
},
// 작업장별 점검 현황
getWorkplaceCheckStatus: async (req, res) => {
try {
const { sessionId } = req.params;
const status = await PatrolModel.getWorkplaceCheckStatus(sessionId);
res.json({ success: true, data: status });
} catch (error) {
console.error('작업장별 점검 현황 조회 오류:', error);
res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' });
}
}
};
module.exports = PatrolController;