Files
tk-factory-services/system1-factory/web/js/tbm/api.js
Hyungi Ahn 61c810bd47 refactor: 프론트엔드 SSO 인증 통합 및 API 경로 정리
- Gateway 로그인/포탈 페이지 SSO 연동
- System1 web/fastapi-bridge API base URL 동적 설정
- SSO 토큰 기반 인증 흐름 통일
- deprecated JS 파일 삭제

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:18:09 +09:00

625 lines
17 KiB
JavaScript

/**
* TBM - API Client
* TBM 관련 모든 API 호출을 관리
*/
class TbmAPI {
constructor() {
this.state = window.TbmState;
this.utils = window.TbmUtils;
console.log('[TbmAPI] 초기화 완료');
}
/**
* 초기 데이터 로드 (작업자, 프로젝트, 안전 체크리스트, 공정, 작업, 작업장)
*/
async loadInitialData() {
try {
// 현재 로그인한 사용자 정보 가져오기
const userInfo = JSON.parse(localStorage.getItem('sso_user') || '{}');
this.state.currentUser = userInfo;
// 병렬로 데이터 로드
await Promise.all([
this.loadWorkers(),
this.loadProjects(),
this.loadSafetyChecks(),
this.loadWorkTypes(),
this.loadTasks(),
this.loadWorkplaces(),
this.loadWorkplaceCategories()
]);
} catch (error) {
console.error(' 초기 데이터 로드 오류:', error);
window.showToast?.('데이터를 불러오는 중 오류가 발생했습니다.', 'error');
}
}
/**
* 작업자 목록 로드 (생산팀 소속만)
*/
async loadWorkers() {
try {
const response = await window.apiCall('/workers?limit=1000&department_id=1');
if (response) {
let workers = Array.isArray(response) ? response : (response.data || []);
// 활성 상태인 작업자만 필터링
workers = workers.filter(w => w.status === 'active' && w.employment_status === 'employed');
this.state.allWorkers = workers;
return workers;
}
} catch (error) {
console.error(' 작업자 로딩 오류:', error);
throw error;
}
}
/**
* 프로젝트 목록 로드 (활성 프로젝트만)
*/
async loadProjects() {
try {
const response = await window.apiCall('/projects?is_active=1');
if (response) {
const projects = Array.isArray(response) ? response : (response.data || []);
this.state.allProjects = projects.filter(p =>
p.is_active === 1 || p.is_active === true || p.is_active === '1'
);
return this.state.allProjects;
}
} catch (error) {
console.error(' 프로젝트 로딩 오류:', error);
throw error;
}
}
/**
* 안전 체크리스트 로드
*/
async loadSafetyChecks() {
try {
const response = await window.apiCall('/tbm/safety-checks');
if (response && response.success) {
this.state.allSafetyChecks = response.data;
return this.state.allSafetyChecks;
}
} catch (error) {
console.error(' 안전 체크리스트 로딩 오류:', error);
}
}
/**
* 공정(Work Types) 목록 로드
*/
async loadWorkTypes() {
try {
const response = await window.apiCall('/daily-work-reports/work-types');
if (response && response.success) {
this.state.allWorkTypes = response.data || [];
return this.state.allWorkTypes;
}
} catch (error) {
console.error(' 공정 로딩 오류:', error);
}
}
/**
* 작업(Tasks) 목록 로드
*/
async loadTasks() {
try {
const response = await window.apiCall('/tasks/active/list');
if (response && response.success) {
this.state.allTasks = response.data || [];
return this.state.allTasks;
}
} catch (error) {
console.error(' 작업 로딩 오류:', error);
}
}
/**
* 작업장 목록 로드
*/
async loadWorkplaces() {
try {
const response = await window.apiCall('/workplaces?is_active=true');
if (response && response.success) {
this.state.allWorkplaces = response.data || [];
return this.state.allWorkplaces;
}
} catch (error) {
console.error(' 작업장 로딩 오류:', error);
}
}
/**
* 작업장 카테고리 로드
*/
async loadWorkplaceCategories() {
try {
const response = await window.apiCall('/workplaces/categories/active/list');
if (response && response.success) {
this.state.allWorkplaceCategories = response.data || [];
return this.state.allWorkplaceCategories;
}
} catch (error) {
console.error(' 작업장 카테고리 로딩 오류:', error);
}
}
/**
* 오늘의 TBM만 로드 (TBM 입력 탭용)
*/
async loadTodayOnlyTbm() {
const today = this.utils.getTodayKST();
try {
const response = await window.apiCall(`/tbm/sessions/date/${today}`);
if (response && response.success) {
this.state.todaySessions = response.data || [];
} else {
this.state.todaySessions = [];
}
return this.state.todaySessions;
} catch (error) {
console.error(' 오늘 TBM 조회 오류:', error);
window.showToast?.('오늘 TBM을 불러오는 중 오류가 발생했습니다.', 'error');
this.state.todaySessions = [];
return [];
}
}
/**
* 최근 TBM을 날짜별로 그룹화하여 로드
*/
async loadRecentTbmGroupedByDate() {
try {
const today = new Date();
const dates = [];
// 최근 N일의 날짜 생성
for (let i = 0; i < this.state.loadedDaysCount; i++) {
const date = new Date(today);
date.setDate(date.getDate() - i);
const dateStr = date.toISOString().split('T')[0];
dates.push(dateStr);
}
// 각 날짜의 TBM 로드
this.state.dateGroupedSessions = {};
this.state.allLoadedSessions = [];
const promises = dates.map(date => window.apiCall(`/tbm/sessions/date/${date}`));
const results = await Promise.all(promises);
results.forEach((response, index) => {
const date = dates[index];
if (response && response.success && response.data && response.data.length > 0) {
const sessions = response.data;
if (sessions.length > 0) {
this.state.dateGroupedSessions[date] = sessions;
this.state.allLoadedSessions = this.state.allLoadedSessions.concat(sessions);
}
}
});
return this.state.dateGroupedSessions;
} catch (error) {
console.error(' TBM 날짜별 로드 오류:', error);
window.showToast?.('TBM을 불러오는 중 오류가 발생했습니다.', 'error');
this.state.dateGroupedSessions = {};
return {};
}
}
/**
* 특정 날짜의 TBM 세션 목록 로드
*/
async loadTbmSessionsByDate(date) {
try {
const response = await window.apiCall(`/tbm/sessions/date/${date}`);
if (response && response.success) {
this.state.allSessions = response.data || [];
} else {
this.state.allSessions = [];
}
return this.state.allSessions;
} catch (error) {
console.error(' TBM 세션 조회 오류:', error);
window.showToast?.('TBM 세션을 불러오는 중 오류가 발생했습니다.', 'error');
this.state.allSessions = [];
return [];
}
}
/**
* TBM 세션 생성
*/
async createTbmSession(sessionData) {
try {
const response = await window.apiCall('/tbm/sessions', 'POST', sessionData);
if (!response || !response.success) {
throw new Error(response?.message || '세션 생성 실패');
}
return response;
} catch (error) {
console.error(' TBM 세션 생성 오류:', error);
throw error;
}
}
/**
* TBM 세션 정보 조회
*/
async getSession(sessionId) {
try {
const response = await window.apiCall(`/tbm/sessions/${sessionId}`);
if (!response || !response.success) {
throw new Error(response?.message || '세션 조회 실패');
}
return response.data;
} catch (error) {
console.error(' TBM 세션 조회 오류:', error);
throw error;
}
}
/**
* TBM 팀원 조회
*/
async getTeamMembers(sessionId) {
try {
const response = await window.apiCall(`/tbm/sessions/${sessionId}/team`);
if (!response || !response.success) {
throw new Error(response?.message || '팀원 조회 실패');
}
return response.data || [];
} catch (error) {
console.error(' TBM 팀원 조회 오류:', error);
throw error;
}
}
/**
* TBM 팀원 일괄 추가
*/
async addTeamMembers(sessionId, members) {
try {
const response = await window.apiCall(
`/tbm/sessions/${sessionId}/team/batch`,
'POST',
{ members }
);
if (!response || !response.success) {
const err = new Error(response?.message || '팀원 추가 실패');
if (response && response.duplicates) err.duplicates = response.duplicates;
throw err;
}
return response;
} catch (error) {
console.error(' TBM 팀원 추가 오류:', error);
throw error;
}
}
/**
* TBM 팀원 전체 삭제
*/
async clearTeamMembers(sessionId) {
try {
const response = await window.apiCall(`/tbm/sessions/${sessionId}/team/clear`, 'DELETE');
return response;
} catch (error) {
console.error(' TBM 팀원 삭제 오류:', error);
throw error;
}
}
/**
* TBM 안전 체크 조회
*/
async getSafetyChecks(sessionId) {
try {
const response = await window.apiCall(`/tbm/sessions/${sessionId}/safety`);
return response?.data || [];
} catch (error) {
console.error(' 안전 체크 조회 오류:', error);
return [];
}
}
/**
* TBM 안전 체크 (필터링된) 조회
*/
async getFilteredSafetyChecks(sessionId) {
try {
const response = await window.apiCall(`/tbm/sessions/${sessionId}/safety-checks/filtered`);
if (!response || !response.success) {
throw new Error(response?.message || '체크리스트를 불러올 수 없습니다.');
}
return response.data;
} catch (error) {
console.error(' 필터링된 안전 체크 조회 오류:', error);
throw error;
}
}
/**
* TBM 안전 체크 저장
*/
async saveSafetyChecks(sessionId, records) {
try {
const response = await window.apiCall(
`/tbm/sessions/${sessionId}/safety`,
'POST',
{ records }
);
if (!response || !response.success) {
throw new Error(response?.message || '저장 실패');
}
return response;
} catch (error) {
console.error(' 안전 체크 저장 오류:', error);
throw error;
}
}
/**
* TBM 세션 완료 처리
*/
async completeTbmSession(sessionId, endTime) {
try {
const response = await window.apiCall(
`/tbm/sessions/${sessionId}/complete`,
'POST',
{ end_time: endTime }
);
if (!response || !response.success) {
throw new Error(response?.message || '완료 처리 실패');
}
return response;
} catch (error) {
console.error(' TBM 완료 처리 오류:', error);
throw error;
}
}
/**
* 작업 인계 저장
*/
async saveHandover(handoverData) {
try {
const response = await window.apiCall('/tbm/handovers', 'POST', handoverData);
if (!response || !response.success) {
throw new Error(response?.message || '인계 요청 실패');
}
return response;
} catch (error) {
console.error(' 작업 인계 저장 오류:', error);
throw error;
}
}
/**
* 카테고리별 작업장 로드
*/
async loadWorkplacesByCategory(categoryId) {
try {
const response = await window.apiCall(`/workplaces?category_id=${categoryId}`);
if (!response || !response.success || !response.data) {
return [];
}
return response.data;
} catch (error) {
console.error(' 작업장 로드 오류:', error);
return [];
}
}
/**
* 작업장 지도 영역 로드
*/
async loadMapRegions(categoryId) {
try {
const response = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`);
if (response && response.success) {
this.state.mapRegions = response.data || [];
return this.state.mapRegions;
}
return [];
} catch (error) {
console.error(' 지도 영역 로드 오류:', error);
return [];
}
}
/**
* TBM 세션 삭제
*/
async deleteSession(sessionId) {
try {
const response = await window.apiCall(`/tbm/sessions/${sessionId}`, 'DELETE');
if (!response || !response.success) {
throw new Error(response?.message || '삭제 실패');
}
return response;
} catch (error) {
console.error(' TBM 세션 삭제 오류:', error);
throw error;
}
}
/**
* TBM 팀원 분할 배정
*/
async splitAssignment(sessionId, splitData) {
try {
const response = await window.apiCall(
`/tbm/sessions/${sessionId}/team/split`,
'POST',
splitData
);
if (!response || !response.success) {
throw new Error(response?.message || '분할 실패');
}
return response;
} catch (error) {
console.error(' 분할 배정 오류:', error);
throw error;
}
}
/**
* TBM 팀원 단일 추가/수정 (POST /team)
*/
async updateTeamMember(sessionId, memberData) {
try {
const response = await window.apiCall(
`/tbm/sessions/${sessionId}/team`,
'POST',
memberData
);
if (!response || !response.success) {
throw new Error(response?.message || '팀원 수정 실패');
}
return response;
} catch (error) {
console.error(' 팀원 수정 오류:', error);
throw error;
}
}
/**
* TBM 인원 이동 (분할→이동 / 빼오기)
*/
async transfer(transferData) {
try {
const response = await window.apiCall('/tbm/transfers', 'POST', transferData);
if (!response || !response.success) {
throw new Error(response?.message || '이동 실패');
}
return response;
} catch (error) {
console.error(' TBM 이동 오류:', error);
throw error;
}
}
/**
* 작업 생성
*/
async createTask(taskData) {
try {
const response = await window.apiCall('/tasks', 'POST', taskData);
if (!response || !response.success) {
throw new Error(response?.message || '작업 생성 실패');
}
return response;
} catch (error) {
console.error(' 작업 생성 오류:', error);
throw error;
}
}
/**
* 활성 작업장 전체 목록 (active/list)
*/
async loadActiveWorkplacesList() {
try {
const response = await window.apiCall('/workplaces/active/list');
if (response && response.success) {
return response.data || [];
}
return [];
} catch (error) {
console.error(' 활성 작업장 목록 오류:', error);
return [];
}
}
/**
* 당일 배정 현황 조회
*/
async loadTodayAssignments(date) {
try {
const response = await window.apiCall(`/tbm/sessions/date/${date}/assignments`);
if (response && response.success) {
return response.data || [];
}
return [];
} catch (error) {
console.error(' 배정 현황 조회 오류:', error);
return [];
}
}
/**
* 특정 날짜의 TBM 세션 조회 (raw - 상태 변경 없음)
*/
async fetchSessionsByDate(date) {
try {
const response = await window.apiCall(`/tbm/sessions/date/${date}`);
if (response && response.success) {
return response.data || [];
}
return [];
} catch (error) {
console.error(' TBM 세션 조회 오류:', error);
return [];
}
}
/**
* TBM 세션 완료 처리 (근태 정보 포함)
*/
async completeTbmWithAttendance(sessionId, attendanceData) {
try {
const response = await window.apiCall(
`/tbm/sessions/${sessionId}/complete`,
'POST',
{ attendance: attendanceData }
);
if (!response || !response.success) {
throw new Error(response?.message || '완료 처리 실패');
}
return response;
} catch (error) {
console.error(' TBM 완료 처리 오류:', error);
throw error;
}
}
}
// 전역 인스턴스 생성
window.TbmAPI = new TbmAPI();
// 하위 호환성: 기존 함수들
window.loadInitialData = () => window.TbmAPI.loadInitialData();
window.loadTodayOnlyTbm = () => window.TbmAPI.loadTodayOnlyTbm();
window.loadTodayTbm = () => window.TbmAPI.loadRecentTbmGroupedByDate();
window.loadAllTbm = () => {
window.TbmState.loadedDaysCount = 30;
return window.TbmAPI.loadRecentTbmGroupedByDate();
};
window.loadRecentTbmGroupedByDate = () => window.TbmAPI.loadRecentTbmGroupedByDate();
window.loadTbmSessionsByDate = (date) => window.TbmAPI.loadTbmSessionsByDate(date);
window.loadWorkplaceCategories = () => window.TbmAPI.loadWorkplaceCategories();
window.loadWorkplacesByCategory = (categoryId) => window.TbmAPI.loadWorkplacesByCategory(categoryId);
// 더 많은 날짜 로드
window.loadMoreTbmDays = async function() {
window.TbmState.loadedDaysCount += 7;
await window.TbmAPI.loadRecentTbmGroupedByDate();
window.showToast?.(`최근 ${window.TbmState.loadedDaysCount}일의 TBM을 로드했습니다.`, 'success');
};
window.deleteTbmSession = (sessionId) => window.TbmAPI.deleteSession(sessionId);
window.fetchSessionsByDate = (date) => window.TbmAPI.fetchSessionsByDate(date);
console.log('[Module] tbm/api.js 로드 완료');