feat: tkuser 통합 관리 서비스 + 전체 시스템 SSO 쿠키 인증 통합
- 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>
This commit is contained in:
@@ -3,7 +3,7 @@ FROM node:18-alpine
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
RUN npm install --omit=dev
|
||||
|
||||
COPY . .
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
const workIssueModel = require('../models/workIssueModel');
|
||||
const imageUploadService = require('../services/imageUploadService');
|
||||
const mProjectService = require('../services/mProjectService');
|
||||
|
||||
// ==================== 신고 카테고리 관리 ====================
|
||||
|
||||
@@ -26,7 +27,7 @@ exports.getAllCategories = (req, res) => {
|
||||
exports.getCategoriesByType = (req, res) => {
|
||||
const { type } = req.params;
|
||||
|
||||
if (!['nonconformity', 'safety'].includes(type)) {
|
||||
if (!['nonconformity', 'safety', 'facility'].includes(type)) {
|
||||
return res.status(400).json({ success: false, error: '유효하지 않은 카테고리 타입입니다.' });
|
||||
}
|
||||
|
||||
@@ -283,16 +284,53 @@ exports.createReport = async (req, res) => {
|
||||
...photoPaths
|
||||
};
|
||||
|
||||
workIssueModel.createReport(reportData, (err, reportId) => {
|
||||
workIssueModel.createReport(reportData, async (err, reportId) => {
|
||||
if (err) {
|
||||
console.error('신고 생성 실패:', err);
|
||||
return res.status(500).json({ success: false, error: '신고 생성 실패' });
|
||||
}
|
||||
|
||||
// 응답 먼저 반환 (사용자 대기 X)
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: '문제 신고가 등록되었습니다.',
|
||||
data: { report_id: reportId }
|
||||
});
|
||||
|
||||
// 부적합 유형이면 System 3(tkqc)으로 비동기 전달
|
||||
try {
|
||||
const categoryInfo = await new Promise((resolve, reject) => {
|
||||
workIssueModel.getCategoryById(issue_category_id, (catErr, data) => {
|
||||
if (catErr) reject(catErr); else resolve(data);
|
||||
});
|
||||
});
|
||||
|
||||
if (categoryInfo && categoryInfo.category_type === 'nonconformity') {
|
||||
// 사진은 System 2에만 저장, URL 참조만 전달
|
||||
const baseUrl = process.env.SYSTEM2_PUBLIC_URL || 'https://tkreport.technicalkorea.net';
|
||||
const photoUrls = Object.values(photoPaths).filter(Boolean)
|
||||
.map(p => `${baseUrl}/api/uploads/${p}`);
|
||||
|
||||
const descParts = [additional_description || categoryInfo.category_name];
|
||||
if (photoUrls.length > 0) {
|
||||
descParts.push('', '[첨부 사진]');
|
||||
photoUrls.forEach((url, i) => descParts.push(`${i + 1}. ${url}`));
|
||||
}
|
||||
|
||||
const result = await mProjectService.sendToMProject({
|
||||
category: categoryInfo.category_name,
|
||||
description: descParts.join('\n'),
|
||||
reporter_name: req.user.name || req.user.username,
|
||||
tk_issue_id: reportId,
|
||||
photos: [] // 사진 복사 안 함 (URL 참조만)
|
||||
});
|
||||
if (result.success && result.mProjectId) {
|
||||
workIssueModel.updateMProjectId(reportId, result.mProjectId, () => {});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('System3 연동 실패 (신고는 정상 저장됨):', e.message);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('신고 생성 에러:', error);
|
||||
|
||||
@@ -198,6 +198,24 @@ const deleteItem = async (itemId, callback) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 카테고리 ID로 단건 조회
|
||||
*/
|
||||
const getCategoryById = async (categoryId, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT category_id, category_type, category_name, description
|
||||
FROM issue_report_categories
|
||||
WHERE category_id = ?`,
|
||||
[categoryId]
|
||||
);
|
||||
callback(null, rows[0] || null);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== 문제 신고 관리 ====================
|
||||
|
||||
// 한국 시간 유틸리티 import
|
||||
@@ -736,6 +754,22 @@ const getStatusLogs = async (reportId, callback) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* m_project_id 업데이트 (System 3 연동 후)
|
||||
*/
|
||||
const updateMProjectId = async (reportId, mProjectId, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
await db.query(
|
||||
`UPDATE work_issue_reports SET m_project_id = ? WHERE report_id = ?`,
|
||||
[mProjectId, reportId]
|
||||
);
|
||||
callback(null);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== 통계 ====================
|
||||
|
||||
/**
|
||||
@@ -854,6 +888,7 @@ module.exports = {
|
||||
// 카테고리
|
||||
getAllCategories,
|
||||
getCategoriesByType,
|
||||
getCategoryById,
|
||||
createCategory,
|
||||
updateCategory,
|
||||
deleteCategory,
|
||||
@@ -872,6 +907,9 @@ module.exports = {
|
||||
updateReport,
|
||||
deleteReport,
|
||||
|
||||
// System 3 연동
|
||||
updateMProjectId,
|
||||
|
||||
// 상태 관리
|
||||
receiveReport,
|
||||
assignReport,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"dev": "node --watch index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-retry": "^1.3.3",
|
||||
"bcrypt": "^6.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
|
||||
Reference in New Issue
Block a user