- tkuser 서비스 신규 추가 (API + Web) - 사용자/권한/프로젝트/부서/작업자/작업장/설비/작업/휴가 통합 관리 - 작업장 탭: 공장→작업장 드릴다운 네비게이션 + 구역지도 클릭 연동 - 작업 탭: 공정(work_types)→작업(tasks) 계층 관리 - 휴가 탭: 유형 관리 + 연차 배정(근로기준법 자동계산) - 전 시스템 SSO 쿠키 인증으로 통합 (.technicalkorea.net 공유) - System 2: 작업 이슈 리포트 기능 강화 - System 3: tkuser API 연동, 페이지 권한 체계 적용 - docker-compose에 tkuser-api, tkuser-web 서비스 추가 - ARCHITECTURE.md, DEPLOYMENT.md 문서 작성 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
142 lines
5.0 KiB
JavaScript
142 lines
5.0 KiB
JavaScript
/**
|
|
* Equipment Controller
|
|
*
|
|
* 설비 CRUD + 지도위치 + 사진
|
|
*/
|
|
|
|
const equipmentModel = require('../models/equipmentModel');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
|
|
// ==================== 기본 CRUD ====================
|
|
|
|
async function getAll(req, res, next) {
|
|
try {
|
|
const filters = {};
|
|
if (req.query.workplace_id) filters.workplace_id = parseInt(req.query.workplace_id);
|
|
if (req.query.equipment_type) filters.equipment_type = req.query.equipment_type;
|
|
if (req.query.status) filters.status = req.query.status;
|
|
if (req.query.search) filters.search = req.query.search;
|
|
const equipments = await equipmentModel.getAll(filters);
|
|
res.json({ success: true, data: equipments });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function getById(req, res, next) {
|
|
try {
|
|
const eq = await equipmentModel.getById(parseInt(req.params.id));
|
|
if (!eq) return res.status(404).json({ success: false, error: '설비를 찾을 수 없습니다' });
|
|
res.json({ success: true, data: eq });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function getByWorkplace(req, res, next) {
|
|
try {
|
|
const equipments = await equipmentModel.getByWorkplace(parseInt(req.params.workplaceId));
|
|
res.json({ success: true, data: equipments });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function create(req, res, next) {
|
|
try {
|
|
const { equipment_code, equipment_name } = req.body;
|
|
if (!equipment_code || !equipment_name) return res.status(400).json({ success: false, error: '관리번호와 설비명은 필수입니다' });
|
|
const dup = await equipmentModel.checkDuplicateCode(equipment_code);
|
|
if (dup) return res.status(409).json({ success: false, error: '이미 존재하는 관리번호입니다' });
|
|
const eq = await equipmentModel.create(req.body);
|
|
res.status(201).json({ success: true, data: eq });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function update(req, res, next) {
|
|
try {
|
|
const id = parseInt(req.params.id);
|
|
if (req.body.equipment_code) {
|
|
const dup = await equipmentModel.checkDuplicateCode(req.body.equipment_code, id);
|
|
if (dup) return res.status(409).json({ success: false, error: '이미 존재하는 관리번호입니다' });
|
|
}
|
|
const eq = await equipmentModel.update(id, req.body);
|
|
if (!eq) return res.status(404).json({ success: false, error: '설비를 찾을 수 없습니다' });
|
|
res.json({ success: true, data: eq });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function remove(req, res, next) {
|
|
try {
|
|
await equipmentModel.remove(parseInt(req.params.id));
|
|
res.json({ success: true, message: '설비가 삭제되었습니다' });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function getTypes(req, res, next) {
|
|
try {
|
|
const types = await equipmentModel.getEquipmentTypes();
|
|
res.json({ success: true, data: types });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function getNextCode(req, res, next) {
|
|
try {
|
|
const code = await equipmentModel.getNextCode(req.query.prefix || 'TKP');
|
|
res.json({ success: true, data: code });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
// ==================== 지도 위치 ====================
|
|
|
|
async function updateMapPosition(req, res, next) {
|
|
try {
|
|
const id = parseInt(req.params.id);
|
|
const positionData = {
|
|
map_x_percent: req.body.map_x_percent,
|
|
map_y_percent: req.body.map_y_percent,
|
|
map_width_percent: req.body.map_width_percent,
|
|
map_height_percent: req.body.map_height_percent
|
|
};
|
|
if (req.body.workplace_id !== undefined) positionData.workplace_id = req.body.workplace_id;
|
|
const eq = await equipmentModel.updateMapPosition(id, positionData);
|
|
res.json({ success: true, data: eq });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
// ==================== 사진 ====================
|
|
|
|
async function addPhoto(req, res, next) {
|
|
try {
|
|
const equipmentId = parseInt(req.params.id);
|
|
if (!req.file) return res.status(400).json({ success: false, error: '사진 파일이 필요합니다' });
|
|
const photoData = {
|
|
photo_path: `/uploads/${req.file.filename}`,
|
|
description: req.body.description || null,
|
|
display_order: parseInt(req.body.display_order) || 0,
|
|
uploaded_by: req.user?.user_id || null
|
|
};
|
|
const result = await equipmentModel.addPhoto(equipmentId, photoData);
|
|
res.status(201).json({ success: true, data: result });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function getPhotos(req, res, next) {
|
|
try {
|
|
const results = await equipmentModel.getPhotos(parseInt(req.params.id));
|
|
res.json({ success: true, data: results });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
async function deletePhoto(req, res, next) {
|
|
try {
|
|
const result = await equipmentModel.deletePhoto(parseInt(req.params.photoId));
|
|
if (result.photo_path) {
|
|
const filePath = path.join(__dirname, '..', result.photo_path);
|
|
fs.unlink(filePath, () => {});
|
|
}
|
|
res.json({ success: true, message: '사진이 삭제되었습니다' });
|
|
} catch (err) { next(err); }
|
|
}
|
|
|
|
module.exports = {
|
|
getAll, getById, getByWorkplace, create, update, remove, getTypes, getNextCode,
|
|
updateMapPosition,
|
|
addPhoto, getPhotos, deletePhoto
|
|
};
|